Home | History | Annotate | Download | only in i965
      1 /*
      2  * Copyright  2011 Intel Corporation
      3  *
      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:
     10  *
     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
     13  * Software.
     14  *
     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
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  */
     23 
     24 #include "brw_context.h"
     25 #include "brw_state.h"
     26 #include "brw_defines.h"
     27 #include "intel_batchbuffer.h"
     28 
     29 #include "main/macros.h"
     30 #include "main/samplerobj.h"
     31 
     32 /**
     33  * Sets the sampler state for a single unit.
     34  */
     35 static void
     36 gen7_update_sampler_state(struct brw_context *brw, int unit, int ss_index,
     37 			  struct gen7_sampler_state *sampler)
     38 {
     39    struct intel_context *intel = &brw->intel;
     40    struct gl_context *ctx = &intel->ctx;
     41    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
     42    struct gl_texture_object *texObj = texUnit->_Current;
     43    struct gl_sampler_object *gl_sampler = _mesa_get_samplerobj(ctx, unit);
     44    bool using_nearest = false;
     45 
     46    /* These don't use samplers at all. */
     47    if (texObj->Target == GL_TEXTURE_BUFFER)
     48       return;
     49 
     50    switch (gl_sampler->MinFilter) {
     51    case GL_NEAREST:
     52       sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
     53       sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
     54       using_nearest = true;
     55       break;
     56    case GL_LINEAR:
     57       sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
     58       sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
     59       break;
     60    case GL_NEAREST_MIPMAP_NEAREST:
     61       sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
     62       sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
     63       break;
     64    case GL_LINEAR_MIPMAP_NEAREST:
     65       sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
     66       sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
     67       break;
     68    case GL_NEAREST_MIPMAP_LINEAR:
     69       sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
     70       sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
     71       break;
     72    case GL_LINEAR_MIPMAP_LINEAR:
     73       sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
     74       sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
     75       break;
     76    default:
     77       break;
     78    }
     79 
     80    /* Set Anisotropy: */
     81    if (gl_sampler->MaxAnisotropy > 1.0) {
     82       sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC;
     83       sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;
     84 
     85       if (gl_sampler->MaxAnisotropy > 2.0) {
     86 	 sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2,
     87 				       BRW_ANISORATIO_16);
     88       }
     89    }
     90    else {
     91       switch (gl_sampler->MagFilter) {
     92       case GL_NEAREST:
     93 	 sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
     94 	 using_nearest = true;
     95 	 break;
     96       case GL_LINEAR:
     97 	 sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
     98 	 break;
     99       default:
    100 	 break;
    101       }
    102    }
    103 
    104    sampler->ss3.r_wrap_mode = translate_wrap_mode(gl_sampler->WrapR,
    105 						  using_nearest);
    106    sampler->ss3.s_wrap_mode = translate_wrap_mode(gl_sampler->WrapS,
    107 						  using_nearest);
    108    sampler->ss3.t_wrap_mode = translate_wrap_mode(gl_sampler->WrapT,
    109 						  using_nearest);
    110 
    111    /* Cube-maps on 965 and later must use the same wrap mode for all 3
    112     * coordinate dimensions.  Futher, only CUBE and CLAMP are valid.
    113     */
    114    if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
    115       if (ctx->Texture.CubeMapSeamless &&
    116 	  (gl_sampler->MinFilter != GL_NEAREST ||
    117 	   gl_sampler->MagFilter != GL_NEAREST)) {
    118 	 sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
    119 	 sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
    120 	 sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
    121       } else {
    122 	 sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
    123 	 sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
    124 	 sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
    125       }
    126    } else if (texObj->Target == GL_TEXTURE_1D) {
    127       /* There's a bug in 1D texture sampling - it actually pays
    128        * attention to the wrap_t value, though it should not.
    129        * Override the wrap_t value here to GL_REPEAT to keep
    130        * any nonexistent border pixels from floating in.
    131        */
    132       sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
    133    }
    134 
    135    /* Set shadow function: */
    136    if (gl_sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
    137       /* Shadowing is "enabled" by emitting a particular sampler
    138        * message (sample_c).  So need to recompile WM program when
    139        * shadow comparison is enabled on each/any texture unit.
    140        */
    141       sampler->ss1.shadow_function =
    142 	 intel_translate_shadow_compare_func(gl_sampler->CompareFunc);
    143    }
    144 
    145    /* Set LOD bias: */
    146    sampler->ss0.lod_bias = S_FIXED(CLAMP(texUnit->LodBias +
    147 					 gl_sampler->LodBias, -16, 15), 8);
    148 
    149    sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
    150    sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */
    151 
    152    /* Set BaseMipLevel, MaxLOD, MinLOD:
    153     *
    154     * XXX: I don't think that using firstLevel, lastLevel works,
    155     * because we always setup the surface state as if firstLevel ==
    156     * level zero.  Probably have to subtract firstLevel from each of
    157     * these:
    158     */
    159    sampler->ss0.base_level = U_FIXED(0, 1);
    160 
    161    sampler->ss1.max_lod = U_FIXED(CLAMP(gl_sampler->MaxLod, 0, 13), 8);
    162    sampler->ss1.min_lod = U_FIXED(CLAMP(gl_sampler->MinLod, 0, 13), 8);
    163 
    164    /* The sampler can handle non-normalized texture rectangle coordinates
    165     * natively
    166     */
    167    if (texObj->Target == GL_TEXTURE_RECTANGLE) {
    168       sampler->ss3.non_normalized_coord = 1;
    169    }
    170 
    171    upload_default_color(brw, gl_sampler, unit, ss_index);
    172 
    173    sampler->ss2.default_color_pointer = brw->wm.sdc_offset[ss_index] >> 5;
    174 
    175    if (sampler->ss0.min_filter != BRW_MAPFILTER_NEAREST)
    176       sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN |
    177                                     BRW_ADDRESS_ROUNDING_ENABLE_V_MIN |
    178                                     BRW_ADDRESS_ROUNDING_ENABLE_R_MIN;
    179    if (sampler->ss0.mag_filter != BRW_MAPFILTER_NEAREST)
    180       sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG |
    181                                     BRW_ADDRESS_ROUNDING_ENABLE_V_MAG |
    182                                     BRW_ADDRESS_ROUNDING_ENABLE_R_MAG;
    183 }
    184 
    185 
    186 static void
    187 gen7_upload_samplers(struct brw_context *brw)
    188 {
    189    struct gl_context *ctx = &brw->intel.ctx;
    190    struct gen7_sampler_state *samplers;
    191 
    192    /* BRW_NEW_VERTEX_PROGRAM and BRW_NEW_FRAGMENT_PROGRAM */
    193    struct gl_program *vs = (struct gl_program *) brw->vertex_program;
    194    struct gl_program *fs = (struct gl_program *) brw->fragment_program;
    195 
    196    GLbitfield SamplersUsed = vs->SamplersUsed | fs->SamplersUsed;
    197 
    198    brw->sampler.count = _mesa_fls(SamplersUsed);
    199 
    200    if (brw->sampler.count == 0)
    201       return;
    202 
    203    samplers = brw_state_batch(brw, AUB_TRACE_SAMPLER_STATE,
    204 			      brw->sampler.count * sizeof(*samplers),
    205 			      32, &brw->sampler.offset);
    206    memset(samplers, 0, brw->sampler.count * sizeof(*samplers));
    207 
    208    for (unsigned s = 0; s < brw->sampler.count; s++) {
    209       if (SamplersUsed & (1 << s)) {
    210          const unsigned unit = (fs->SamplersUsed & (1 << s)) ?
    211             fs->SamplerUnits[s] : vs->SamplerUnits[s];
    212          if (ctx->Texture.Unit[unit]._ReallyEnabled)
    213             gen7_update_sampler_state(brw, unit, s, &samplers[s]);
    214       }
    215    }
    216 
    217    brw->state.dirty.cache |= CACHE_NEW_SAMPLER;
    218 }
    219 
    220 const struct brw_tracked_state gen7_samplers = {
    221    .dirty = {
    222       .mesa = _NEW_TEXTURE,
    223       .brw = BRW_NEW_BATCH |
    224              BRW_NEW_VERTEX_PROGRAM |
    225              BRW_NEW_FRAGMENT_PROGRAM,
    226       .cache = 0
    227    },
    228    .emit = gen7_upload_samplers,
    229 };
    230