Home | History | Annotate | Download | only in nv30
      1 /*
      2  * Copyright 2012 Red Hat Inc.
      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 shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20  * OTHER DEALINGS IN THE SOFTWARE.
     21  *
     22  * Authors: Ben Skeggs
     23  *
     24  */
     25 
     26 #include "util/u_inlines.h"
     27 
     28 #include "nv_object.xml.h"
     29 #include "nv30/nv30-40_3d.xml.h"
     30 #include "nv30/nv30_context.h"
     31 #include "nv30/nv30_format.h"
     32 
     33 void
     34 nv30_fragtex_validate(struct nv30_context *nv30)
     35 {
     36    struct pipe_screen *pscreen = &nv30->screen->base.base;
     37    struct nouveau_object *eng3d = nv30->screen->eng3d;
     38    struct nouveau_pushbuf *push = nv30->base.pushbuf;
     39    unsigned dirty = nv30->fragprog.dirty_samplers;
     40 
     41    while (dirty) {
     42       unsigned unit = ffs(dirty) - 1;
     43       struct nv30_sampler_view *sv = (void *)nv30->fragprog.textures[unit];
     44       struct nv30_sampler_state *ss = nv30->fragprog.samplers[unit];
     45 
     46       PUSH_RESET(push, BUFCTX_FRAGTEX(unit));
     47 
     48       if (ss && sv) {
     49          const struct nv30_texfmt *fmt = nv30_texfmt(pscreen, sv->pipe.format);
     50          struct pipe_resource *pt = sv->pipe.texture;
     51          struct nv30_miptree *mt = nv30_miptree(pt);
     52          unsigned min_lod, max_lod;
     53          u32 filter = sv->filt | (ss->filt & sv->filt_mask);
     54          u32 format = sv->fmt | ss->fmt;
     55          u32 enable = ss->en;
     56 
     57          /* handle base_level when not using a mip filter, min/max level
     58           * is unfortunately ignored by the hardware otherwise
     59           */
     60          if (ss->pipe.min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
     61             if (sv->base_lod)
     62                filter += 0x00020000; /* N/L -> NMN/LMN */
     63             max_lod = sv->base_lod;
     64             min_lod = sv->base_lod;
     65          } else {
     66             max_lod = MIN2(ss->max_lod + sv->base_lod, sv->high_lod);
     67             min_lod = MIN2(ss->min_lod + sv->base_lod, max_lod);
     68          }
     69 
     70          if (eng3d->oclass >= NV40_3D_CLASS) {
     71             /* this is a tad stupid of the hardware, but there's no non-rcomp
     72              * z16/z24 texture formats to be had, we have to suffer and lose
     73              * some precision to handle this case.
     74              */
     75             if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) {
     76                if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z16)
     77                   format |= NV40_3D_TEX_FORMAT_FORMAT_A8L8;
     78                else
     79                if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z24)
     80                   format |= NV40_3D_TEX_FORMAT_FORMAT_A16L16;
     81                else
     82                   format |= fmt->nv40;
     83             } else {
     84                format |= fmt->nv40;
     85             }
     86 
     87             enable |= (min_lod << 19) | (max_lod << 7);
     88             enable |= NV40_3D_TEX_ENABLE_ENABLE;
     89 
     90             BEGIN_NV04(push, NV40_3D(TEX_SIZE1(unit)), 1);
     91             PUSH_DATA (push, sv->npot_size1);
     92          } else {
     93             /* this is a tad stupid of the hardware, but there's no non-rcomp
     94              * z16/z24 texture formats to be had, we have to suffer and lose
     95              * some precision to handle this case.
     96              */
     97             if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) {
     98                if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z16) {
     99                   if (ss->pipe.normalized_coords)
    100                      format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8;
    101                   else
    102                      format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8_RECT;
    103                } else
    104                if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z24) {
    105                   if (ss->pipe.normalized_coords)
    106                      format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16;
    107                   else
    108                      format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16_RECT;
    109                } else {
    110                   if (ss->pipe.normalized_coords)
    111                      format |= fmt->nv30;
    112                   else
    113                      format |= fmt->nv30_rect;
    114                }
    115             } else {
    116                if (ss->pipe.normalized_coords)
    117                   format |= fmt->nv30;
    118                else
    119                   format |= fmt->nv30_rect;
    120             }
    121 
    122             enable |= NV30_3D_TEX_ENABLE_ENABLE;
    123             enable |= (min_lod << 18) | (max_lod << 6);
    124          }
    125 
    126          BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8);
    127          PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), BUFCTX_FRAGTEX(unit),
    128                           mt->base.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
    129          PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), BUFCTX_FRAGTEX(unit),
    130                           mt->base.bo, format, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD,
    131                           NV30_3D_TEX_FORMAT_DMA0,
    132                           NV30_3D_TEX_FORMAT_DMA1);
    133          PUSH_DATA (push, sv->wrap | (ss->wrap & sv->wrap_mask));
    134          PUSH_DATA (push, enable);
    135          PUSH_DATA (push, sv->swz);
    136          PUSH_DATA (push, filter);
    137          PUSH_DATA (push, sv->npot_size0);
    138          PUSH_DATA (push, ss->bcol);
    139          BEGIN_NV04(push, NV30_3D(TEX_FILTER_OPTIMIZATION(unit)), 1);
    140          PUSH_DATA (push, nv30->config.filter);
    141       } else {
    142          BEGIN_NV04(push, NV30_3D(TEX_ENABLE(unit)), 1);
    143          PUSH_DATA (push, 0);
    144       }
    145 
    146       dirty &= ~(1 << unit);
    147    }
    148 
    149    nv30->fragprog.dirty_samplers = 0;
    150 }
    151 
    152 void
    153 nv30_fragtex_sampler_states_bind(struct pipe_context *pipe,
    154                                  unsigned nr, void **hwcso)
    155 {
    156    struct nv30_context *nv30 = nv30_context(pipe);
    157    unsigned i;
    158 
    159    for (i = 0; i < nr; i++) {
    160       nv30->fragprog.samplers[i] = hwcso[i];
    161       nv30->fragprog.dirty_samplers |= (1 << i);
    162    }
    163 
    164    for (; i < nv30->fragprog.num_samplers; i++) {
    165       nv30->fragprog.samplers[i] = NULL;
    166       nv30->fragprog.dirty_samplers |= (1 << i);
    167    }
    168 
    169    nv30->fragprog.num_samplers = nr;
    170    nv30->dirty |= NV30_NEW_FRAGTEX;
    171 }
    172 
    173 
    174 void
    175 nv30_fragtex_set_sampler_views(struct pipe_context *pipe, unsigned nr,
    176                                struct pipe_sampler_view **views)
    177 {
    178    struct nv30_context *nv30 = nv30_context(pipe);
    179    unsigned i;
    180 
    181    for (i = 0; i < nr; i++) {
    182       nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FRAGTEX(i));
    183       pipe_sampler_view_reference(&nv30->fragprog.textures[i], views[i]);
    184       nv30->fragprog.dirty_samplers |= (1 << i);
    185    }
    186 
    187    for (; i < nv30->fragprog.num_textures; i++) {
    188       nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FRAGTEX(i));
    189       pipe_sampler_view_reference(&nv30->fragprog.textures[i], NULL);
    190       nv30->fragprog.dirty_samplers |= (1 << i);
    191    }
    192 
    193    nv30->fragprog.num_textures = nr;
    194    nv30->dirty |= NV30_NEW_FRAGTEX;
    195 }
    196 
    197 
    198 static void
    199 nv30_set_sampler_views(struct pipe_context *pipe, enum pipe_shader_type shader,
    200                        unsigned start, unsigned nr,
    201                        struct pipe_sampler_view **views)
    202 {
    203    assert(start == 0);
    204    switch (shader) {
    205    case PIPE_SHADER_FRAGMENT:
    206       nv30_fragtex_set_sampler_views(pipe, nr, views);
    207       break;
    208    case PIPE_SHADER_VERTEX:
    209       nv40_verttex_set_sampler_views(pipe, nr, views);
    210       break;
    211    default:
    212       ;
    213    }
    214 }
    215 
    216 
    217 void
    218 nv30_fragtex_init(struct pipe_context *pipe)
    219 {
    220    pipe->set_sampler_views = nv30_set_sampler_views;
    221 }
    222