1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2015 Red Hat 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "nir.h" 25bf215546Sopenharmony_ci#include "nir_builder.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci/* Lower glBitmap(). 28bf215546Sopenharmony_ci * 29bf215546Sopenharmony_ci * This is based on the logic in st_get_bitmap_shader() in TGSI compiler. 30bf215546Sopenharmony_ci * From st_cb_bitmap.c: 31bf215546Sopenharmony_ci * 32bf215546Sopenharmony_ci * glBitmaps are drawn as textured quads. The user's bitmap pattern 33bf215546Sopenharmony_ci * is stored in a texture image. An alpha8 texture format is used. 34bf215546Sopenharmony_ci * The fragment shader samples a bit (texel) from the texture, then 35bf215546Sopenharmony_ci * discards the fragment if the bit is off. 36bf215546Sopenharmony_ci * 37bf215546Sopenharmony_ci * Note that we actually store the inverse image of the bitmap to 38bf215546Sopenharmony_ci * simplify the fragment program. An "on" bit gets stored as texel=0x0 39bf215546Sopenharmony_ci * and an "off" bit is stored as texel=0xff. Then we kill the 40bf215546Sopenharmony_ci * fragment if the negated texel value is less than zero. 41bf215546Sopenharmony_ci * 42bf215546Sopenharmony_ci * Note that the texture format will be, according to what driver supports, 43bf215546Sopenharmony_ci * in order of preference (with swizzle): 44bf215546Sopenharmony_ci * 45bf215546Sopenharmony_ci * I8_UNORM - .xxxx 46bf215546Sopenharmony_ci * A8_UNORM - .000x 47bf215546Sopenharmony_ci * L8_UNORM - .xxx1 48bf215546Sopenharmony_ci * 49bf215546Sopenharmony_ci * If L8_UNORM, options->swizzle_xxxx is true. Otherwise we can just use 50bf215546Sopenharmony_ci * the .w comp. 51bf215546Sopenharmony_ci * 52bf215546Sopenharmony_ci * Run before nir_lower_io. 53bf215546Sopenharmony_ci */ 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_cistatic nir_variable * 56bf215546Sopenharmony_ciget_texcoord(nir_shader *shader) 57bf215546Sopenharmony_ci{ 58bf215546Sopenharmony_ci nir_variable *texcoord = 59bf215546Sopenharmony_ci nir_find_variable_with_location(shader, nir_var_shader_in, 60bf215546Sopenharmony_ci VARYING_SLOT_TEX0); 61bf215546Sopenharmony_ci /* otherwise create it: */ 62bf215546Sopenharmony_ci if (texcoord == NULL) { 63bf215546Sopenharmony_ci texcoord = nir_variable_create(shader, 64bf215546Sopenharmony_ci nir_var_shader_in, 65bf215546Sopenharmony_ci glsl_vec4_type(), 66bf215546Sopenharmony_ci "gl_TexCoord"); 67bf215546Sopenharmony_ci texcoord->data.location = VARYING_SLOT_TEX0; 68bf215546Sopenharmony_ci } 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci return texcoord; 71bf215546Sopenharmony_ci} 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_cistatic void 74bf215546Sopenharmony_cilower_bitmap(nir_shader *shader, nir_builder *b, 75bf215546Sopenharmony_ci const nir_lower_bitmap_options *options) 76bf215546Sopenharmony_ci{ 77bf215546Sopenharmony_ci nir_ssa_def *texcoord; 78bf215546Sopenharmony_ci nir_tex_instr *tex; 79bf215546Sopenharmony_ci nir_ssa_def *cond; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci texcoord = nir_load_var(b, get_texcoord(shader)); 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci const struct glsl_type *sampler2D = 84bf215546Sopenharmony_ci glsl_sampler_type(GLSL_SAMPLER_DIM_2D, false, false, GLSL_TYPE_FLOAT); 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci nir_variable *tex_var = 87bf215546Sopenharmony_ci nir_variable_create(shader, nir_var_uniform, sampler2D, "bitmap_tex"); 88bf215546Sopenharmony_ci tex_var->data.binding = options->sampler; 89bf215546Sopenharmony_ci tex_var->data.explicit_binding = true; 90bf215546Sopenharmony_ci tex_var->data.how_declared = nir_var_hidden; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci nir_deref_instr *tex_deref = nir_build_deref_var(b, tex_var); 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci tex = nir_tex_instr_create(shader, 3); 95bf215546Sopenharmony_ci tex->op = nir_texop_tex; 96bf215546Sopenharmony_ci tex->sampler_dim = GLSL_SAMPLER_DIM_2D; 97bf215546Sopenharmony_ci tex->coord_components = 2; 98bf215546Sopenharmony_ci tex->dest_type = nir_type_float32; 99bf215546Sopenharmony_ci tex->src[0].src_type = nir_tex_src_texture_deref; 100bf215546Sopenharmony_ci tex->src[0].src = nir_src_for_ssa(&tex_deref->dest.ssa); 101bf215546Sopenharmony_ci tex->src[1].src_type = nir_tex_src_sampler_deref; 102bf215546Sopenharmony_ci tex->src[1].src = nir_src_for_ssa(&tex_deref->dest.ssa); 103bf215546Sopenharmony_ci tex->src[2].src_type = nir_tex_src_coord; 104bf215546Sopenharmony_ci tex->src[2].src = 105bf215546Sopenharmony_ci nir_src_for_ssa(nir_channels(b, texcoord, 106bf215546Sopenharmony_ci (1 << tex->coord_components) - 1)); 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL); 109bf215546Sopenharmony_ci nir_builder_instr_insert(b, &tex->instr); 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci /* kill if tex != 0.0.. take .x or .w channel according to format: */ 112bf215546Sopenharmony_ci cond = nir_f2b(b, nir_channel(b, &tex->dest.ssa, 113bf215546Sopenharmony_ci options->swizzle_xxxx ? 0 : 3)); 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci nir_discard_if(b, cond); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci shader->info.fs.uses_discard = true; 118bf215546Sopenharmony_ci} 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_cistatic void 121bf215546Sopenharmony_cilower_bitmap_impl(nir_function_impl *impl, 122bf215546Sopenharmony_ci const nir_lower_bitmap_options *options) 123bf215546Sopenharmony_ci{ 124bf215546Sopenharmony_ci nir_builder b; 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci nir_builder_init(&b, impl); 127bf215546Sopenharmony_ci b.cursor = nir_before_cf_list(&impl->body); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci lower_bitmap(impl->function->shader, &b, options); 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci nir_metadata_preserve(impl, nir_metadata_block_index | 132bf215546Sopenharmony_ci nir_metadata_dominance); 133bf215546Sopenharmony_ci} 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_civoid 136bf215546Sopenharmony_cinir_lower_bitmap(nir_shader *shader, 137bf215546Sopenharmony_ci const nir_lower_bitmap_options *options) 138bf215546Sopenharmony_ci{ 139bf215546Sopenharmony_ci assert(shader->info.stage == MESA_SHADER_FRAGMENT); 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci lower_bitmap_impl(nir_shader_get_entrypoint(shader), options); 142bf215546Sopenharmony_ci} 143