Home | History | Annotate | Download | only in nouveau
      1 /*
      2  * Copyright (C) 2009 Francisco Jerez.
      3  * All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sublicense, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the
     14  * next paragraph) shall be included in all copies or substantial
     15  * portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  */
     26 
     27 #include "nouveau_driver.h"
     28 #include "nouveau_context.h"
     29 #include "nouveau_gldefs.h"
     30 #include "nouveau_texture.h"
     31 #include "nv10_3d.xml.h"
     32 #include "nouveau_util.h"
     33 #include "nv10_driver.h"
     34 #include "main/samplerobj.h"
     35 
     36 void
     37 nv10_emit_tex_gen(struct gl_context *ctx, int emit)
     38 {
     39 	const int i = emit - NOUVEAU_STATE_TEX_GEN0;
     40 	struct nouveau_context *nctx = to_nouveau_context(ctx);
     41 	struct nouveau_pushbuf *push = context_push(ctx);
     42 	struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
     43 	int j;
     44 
     45 	for (j = 0; j < 4; j++) {
     46 		if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) {
     47 			struct gl_texgen *coord = get_texgen_coord(unit, j);
     48 			float *k = get_texgen_coeff(coord);
     49 
     50 			if (k) {
     51 				BEGIN_NV04(push, NV10_3D(TEX_GEN_COEFF(i, j)), 4);
     52 				PUSH_DATAp(push, k, 4);
     53 			}
     54 
     55 			BEGIN_NV04(push, NV10_3D(TEX_GEN_MODE(i,j)), 1);
     56 			PUSH_DATA (push, nvgl_texgen_mode(coord->Mode));
     57 
     58 		} else {
     59 			BEGIN_NV04(push, NV10_3D(TEX_GEN_MODE(i,j)), 1);
     60 			PUSH_DATA (push, 0);
     61 		}
     62 	}
     63 
     64 	context_dirty_i(ctx, TEX_MAT, i);
     65 }
     66 
     67 void
     68 nv10_emit_tex_mat(struct gl_context *ctx, int emit)
     69 {
     70 	const int i = emit - NOUVEAU_STATE_TEX_MAT0;
     71 	struct nouveau_context *nctx = to_nouveau_context(ctx);
     72 	struct nouveau_pushbuf *push = context_push(ctx);
     73 
     74 	if (nctx->fallback == HWTNL &&
     75 	    ((ctx->Texture._TexMatEnabled & 1 << i) ||
     76 	     ctx->Texture.Unit[i]._GenFlags)) {
     77 		BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(i)), 1);
     78 		PUSH_DATA (push, 1);
     79 
     80 		BEGIN_NV04(push, NV10_3D(TEX_MATRIX(i, 0)), 16);
     81 		PUSH_DATAm(push, ctx->TextureMatrixStack[i].Top->m);
     82 
     83 	} else {
     84 		BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(i)), 1);
     85 		PUSH_DATA (push, 0);
     86 	}
     87 }
     88 
     89 static uint32_t
     90 get_tex_format_pot(struct gl_texture_image *ti)
     91 {
     92 	switch (ti->TexFormat) {
     93 	case MESA_FORMAT_B8G8R8A8_UNORM:
     94 		return NV10_3D_TEX_FORMAT_FORMAT_A8R8G8B8;
     95 
     96 	case MESA_FORMAT_B8G8R8X8_UNORM:
     97 		return NV10_3D_TEX_FORMAT_FORMAT_X8R8G8B8;
     98 
     99 	case MESA_FORMAT_B5G5R5A1_UNORM:
    100 		return NV10_3D_TEX_FORMAT_FORMAT_A1R5G5B5;
    101 
    102 	case MESA_FORMAT_B4G4R4A4_UNORM:
    103 		return NV10_3D_TEX_FORMAT_FORMAT_A4R4G4B4;
    104 
    105 	case MESA_FORMAT_B5G6R5_UNORM:
    106 		return NV10_3D_TEX_FORMAT_FORMAT_R5G6B5;
    107 
    108 	case MESA_FORMAT_A_UNORM8:
    109 	case MESA_FORMAT_I_UNORM8:
    110 		return NV10_3D_TEX_FORMAT_FORMAT_I8;
    111 
    112 	case MESA_FORMAT_L_UNORM8:
    113 		return NV10_3D_TEX_FORMAT_FORMAT_L8;
    114 
    115 	case MESA_FORMAT_RGB_DXT1:
    116 	case MESA_FORMAT_RGBA_DXT1:
    117 		return NV10_3D_TEX_FORMAT_FORMAT_DXT1;
    118 
    119 	case MESA_FORMAT_RGBA_DXT3:
    120 		return NV10_3D_TEX_FORMAT_FORMAT_DXT3;
    121 
    122 	case MESA_FORMAT_RGBA_DXT5:
    123 		return NV10_3D_TEX_FORMAT_FORMAT_DXT5;
    124 
    125 	default:
    126 		assert(0);
    127 	}
    128 }
    129 
    130 static uint32_t
    131 get_tex_format_rect(struct gl_texture_image *ti)
    132 {
    133 	switch (ti->TexFormat) {
    134 	case MESA_FORMAT_B5G5R5A1_UNORM:
    135 		return NV10_3D_TEX_FORMAT_FORMAT_A1R5G5B5_RECT;
    136 
    137 	case MESA_FORMAT_B5G6R5_UNORM:
    138 		return NV10_3D_TEX_FORMAT_FORMAT_R5G6B5_RECT;
    139 
    140 	case MESA_FORMAT_B8G8R8A8_UNORM:
    141 	case MESA_FORMAT_B8G8R8X8_UNORM:
    142 		return NV10_3D_TEX_FORMAT_FORMAT_A8R8G8B8_RECT;
    143 
    144 	case MESA_FORMAT_A_UNORM8:
    145 	case MESA_FORMAT_L_UNORM8:
    146 	case MESA_FORMAT_I_UNORM8:
    147 		return NV10_3D_TEX_FORMAT_FORMAT_I8_RECT;
    148 
    149 	default:
    150 		assert(0);
    151 	}
    152 }
    153 
    154 void
    155 nv10_emit_tex_obj(struct gl_context *ctx, int emit)
    156 {
    157 	const int i = emit - NOUVEAU_STATE_TEX_OBJ0;
    158 	struct nouveau_pushbuf *push = context_push(ctx);
    159 	const int bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART | NOUVEAU_BO_VRAM;
    160 	struct gl_texture_object *t;
    161 	struct nouveau_surface *s;
    162 	struct gl_texture_image *ti;
    163 	const struct gl_sampler_object *sa;
    164 	uint32_t tx_format, tx_filter, tx_enable;
    165 
    166 	PUSH_RESET(push, BUFCTX_TEX(i));
    167 
    168 	if (!ctx->Texture.Unit[i]._Current) {
    169 		BEGIN_NV04(push, NV10_3D(TEX_ENABLE(i)), 1);
    170 		PUSH_DATA (push, 0);
    171 		return;
    172 	}
    173 
    174 	t = ctx->Texture.Unit[i]._Current;
    175 	s = &to_nouveau_texture(t)->surfaces[t->BaseLevel];
    176 	ti = t->Image[0][t->BaseLevel];
    177 	sa = _mesa_get_samplerobj(ctx, i);
    178 
    179 	if (!nouveau_texture_validate(ctx, t))
    180 		return;
    181 
    182 	/* Recompute the texturing registers. */
    183 	tx_format = nvgl_wrap_mode(sa->WrapT) << 28
    184 		| nvgl_wrap_mode(sa->WrapS) << 24
    185 		| ti->HeightLog2 << 20
    186 		| ti->WidthLog2 << 16
    187 		| 5 << 4 | 1 << 12;
    188 
    189 	tx_filter = nvgl_filter_mode(sa->MagFilter) << 28
    190 		| nvgl_filter_mode(sa->MinFilter) << 24;
    191 
    192 	tx_enable = NV10_3D_TEX_ENABLE_ENABLE
    193 		| log2i(sa->MaxAnisotropy) << 4;
    194 
    195 	if (t->Target == GL_TEXTURE_RECTANGLE) {
    196 		BEGIN_NV04(push, NV10_3D(TEX_NPOT_PITCH(i)), 1);
    197 		PUSH_DATA (push, s->pitch << 16);
    198 		BEGIN_NV04(push, NV10_3D(TEX_NPOT_SIZE(i)), 1);
    199 		PUSH_DATA (push, align(s->width, 2) << 16 | s->height);
    200 
    201 		tx_format |= get_tex_format_rect(ti);
    202 	} else {
    203 		tx_format |= get_tex_format_pot(ti);
    204 	}
    205 
    206 	if (sa->MinFilter != GL_NEAREST &&
    207 	    sa->MinFilter != GL_LINEAR) {
    208 		int lod_min = sa->MinLod;
    209 		int lod_max = MIN2(sa->MaxLod, t->_MaxLambda);
    210 		int lod_bias = sa->LodBias
    211 			+ ctx->Texture.Unit[i].LodBias;
    212 
    213 		lod_max = CLAMP(lod_max, 0, 15);
    214 		lod_min = CLAMP(lod_min, 0, 15);
    215 		lod_bias = CLAMP(lod_bias, 0, 15);
    216 
    217 		tx_format |= NV10_3D_TEX_FORMAT_MIPMAP;
    218 		tx_filter |= lod_bias << 8;
    219 		tx_enable |= lod_min << 26
    220 			| lod_max << 14;
    221 	}
    222 
    223 	/* Write it to the hardware. */
    224 	BEGIN_NV04(push, NV10_3D(TEX_FORMAT(i)), 1);
    225 	PUSH_MTHD (push, NV10_3D(TEX_FORMAT(i)), BUFCTX_TEX(i),
    226 			 s->bo, tx_format, bo_flags | NOUVEAU_BO_OR,
    227 			 NV10_3D_TEX_FORMAT_DMA0,
    228 			 NV10_3D_TEX_FORMAT_DMA1);
    229 
    230 	BEGIN_NV04(push, NV10_3D(TEX_OFFSET(i)), 1);
    231 	PUSH_MTHDl(push, NV10_3D(TEX_OFFSET(i)), BUFCTX_TEX(i),
    232 			 s->bo, s->offset, bo_flags);
    233 
    234 	BEGIN_NV04(push, NV10_3D(TEX_FILTER(i)), 1);
    235 	PUSH_DATA (push, tx_filter);
    236 
    237 	BEGIN_NV04(push, NV10_3D(TEX_ENABLE(i)), 1);
    238 	PUSH_DATA (push, tx_enable);
    239 }
    240 
    241