svga_pipe_sampler.c revision c50fe2c55cfe9c858b7b7859da79edb0693ee8bd
1/********************************************************** 2 * Copyright 2008-2009 VMware, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 **********************************************************/ 25 26#include "pipe/p_inlines.h" 27#include "pipe/p_defines.h" 28#include "util/u_math.h" 29#include "util/u_memory.h" 30#include "util/u_pack_color.h" 31#include "tgsi/tgsi_parse.h" 32 33#include "svga_context.h" 34#include "svga_screen_texture.h" 35 36#include "svga_debug.h" 37 38static INLINE unsigned 39translate_wrap_mode(unsigned wrap) 40{ 41 switch (wrap) { 42 case PIPE_TEX_WRAP_REPEAT: 43 return SVGA3D_TEX_ADDRESS_WRAP; 44 45 case PIPE_TEX_WRAP_CLAMP: 46 return SVGA3D_TEX_ADDRESS_CLAMP; 47 48 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 49 /* Unfortunately SVGA3D_TEX_ADDRESS_EDGE not respected by 50 * hardware. 51 */ 52 return SVGA3D_TEX_ADDRESS_CLAMP; 53 54 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 55 return SVGA3D_TEX_ADDRESS_BORDER; 56 57 case PIPE_TEX_WRAP_MIRROR_REPEAT: 58 return SVGA3D_TEX_ADDRESS_MIRROR; 59 60 case PIPE_TEX_WRAP_MIRROR_CLAMP: 61 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 62 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 63 return SVGA3D_TEX_ADDRESS_MIRRORONCE; 64 65 default: 66 assert(0); 67 return SVGA3D_TEX_ADDRESS_WRAP; 68 } 69} 70 71static INLINE unsigned translate_img_filter( unsigned filter ) 72{ 73 switch (filter) { 74 case PIPE_TEX_FILTER_NEAREST: return SVGA3D_TEX_FILTER_NEAREST; 75 case PIPE_TEX_FILTER_LINEAR: return SVGA3D_TEX_FILTER_LINEAR; 76 case PIPE_TEX_FILTER_ANISO: return SVGA3D_TEX_FILTER_ANISOTROPIC; 77 default: 78 assert(0); 79 return SVGA3D_TEX_FILTER_NEAREST; 80 } 81} 82 83static INLINE unsigned translate_mip_filter( unsigned filter ) 84{ 85 switch (filter) { 86 case PIPE_TEX_MIPFILTER_NONE: return SVGA3D_TEX_FILTER_NONE; 87 case PIPE_TEX_MIPFILTER_NEAREST: return SVGA3D_TEX_FILTER_NEAREST; 88 case PIPE_TEX_MIPFILTER_LINEAR: return SVGA3D_TEX_FILTER_LINEAR; 89 default: 90 assert(0); 91 return SVGA3D_TEX_FILTER_NONE; 92 } 93} 94 95static void * 96svga_create_sampler_state(struct pipe_context *pipe, 97 const struct pipe_sampler_state *sampler) 98{ 99 struct svga_context *svga = svga_context(pipe); 100 struct svga_sampler_state *cso = CALLOC_STRUCT( svga_sampler_state ); 101 102 cso->mipfilter = translate_mip_filter(sampler->min_mip_filter); 103 cso->magfilter = translate_img_filter( sampler->mag_img_filter ); 104 cso->minfilter = translate_img_filter( sampler->min_img_filter ); 105 cso->aniso_level = MAX2( (unsigned) sampler->max_anisotropy, 1 ); 106 cso->lod_bias = sampler->lod_bias; 107 cso->addressu = translate_wrap_mode(sampler->wrap_s); 108 cso->addressv = translate_wrap_mode(sampler->wrap_t); 109 cso->addressw = translate_wrap_mode(sampler->wrap_r); 110 cso->normalized_coords = sampler->normalized_coords; 111 cso->compare_mode = sampler->compare_mode; 112 cso->compare_func = sampler->compare_func; 113 114 { 115 ubyte r = float_to_ubyte(sampler->border_color[0]); 116 ubyte g = float_to_ubyte(sampler->border_color[1]); 117 ubyte b = float_to_ubyte(sampler->border_color[2]); 118 ubyte a = float_to_ubyte(sampler->border_color[3]); 119 120 util_pack_color_ub( r, g, b, a, 121 PIPE_FORMAT_B8G8R8A8_UNORM, 122 &cso->bordercolor ); 123 } 124 125 /* No SVGA3D support for: 126 * - min/max LOD clamping 127 */ 128 cso->min_lod = 0; 129 cso->view_min_lod = MAX2(sampler->min_lod, 0); 130 cso->view_max_lod = MAX2(sampler->max_lod, 0); 131 132 /* Use min_mipmap */ 133 if (svga->debug.use_min_mipmap) { 134 if (cso->view_min_lod == cso->view_max_lod) { 135 cso->min_lod = cso->view_min_lod; 136 cso->view_min_lod = 0; 137 cso->view_max_lod = 1000; /* Just a high number */ 138 cso->mipfilter = SVGA3D_TEX_FILTER_NONE; 139 } 140 } 141 142 SVGA_DBG(DEBUG_VIEWS, "min %u, view(min %u, max %u) lod, mipfilter %s\n", 143 cso->min_lod, cso->view_min_lod, cso->view_max_lod, 144 cso->mipfilter == SVGA3D_TEX_FILTER_NONE ? "SVGA3D_TEX_FILTER_NONE" : "SOMETHING"); 145 146 return cso; 147} 148 149static void svga_bind_sampler_states(struct pipe_context *pipe, 150 unsigned num, void **sampler) 151{ 152 struct svga_context *svga = svga_context(pipe); 153 unsigned i; 154 155 assert(num <= PIPE_MAX_SAMPLERS); 156 157 /* Check for no-op */ 158 if (num == svga->curr.num_samplers && 159 !memcmp(svga->curr.sampler, sampler, num * sizeof(void *))) { 160 debug_printf("sampler noop\n"); 161 return; 162 } 163 164 for (i = 0; i < num; i++) 165 svga->curr.sampler[i] = sampler[i]; 166 167 for (i = num; i < svga->curr.num_samplers; i++) 168 svga->curr.sampler[i] = NULL; 169 170 svga->curr.num_samplers = num; 171 svga->dirty |= SVGA_NEW_SAMPLER; 172} 173 174static void svga_delete_sampler_state(struct pipe_context *pipe, 175 void *sampler) 176{ 177 FREE(sampler); 178} 179 180 181static void svga_set_sampler_textures(struct pipe_context *pipe, 182 unsigned num, 183 struct pipe_texture **texture) 184{ 185 struct svga_context *svga = svga_context(pipe); 186 unsigned flag_1d = 0; 187 unsigned flag_srgb = 0; 188 uint i; 189 190 assert(num <= PIPE_MAX_SAMPLERS); 191 192 /* Check for no-op */ 193 if (num == svga->curr.num_textures && 194 !memcmp(svga->curr.texture, texture, num * sizeof(struct pipe_texture *))) { 195 if (0) debug_printf("texture noop\n"); 196 return; 197 } 198 199 for (i = 0; i < num; i++) { 200 pipe_texture_reference(&svga->curr.texture[i], 201 texture[i]); 202 203 if (!texture[i]) 204 continue; 205 206 if (texture[i]->format == PIPE_FORMAT_A8R8G8B8_SRGB) 207 flag_srgb |= 1 << i; 208 209 if (texture[i]->target == PIPE_TEXTURE_1D) 210 flag_1d |= 1 << i; 211 } 212 213 for (i = num; i < svga->curr.num_textures; i++) 214 pipe_texture_reference(&svga->curr.texture[i], 215 NULL); 216 217 svga->curr.num_textures = num; 218 svga->dirty |= SVGA_NEW_TEXTURE_BINDING; 219 220 if (flag_srgb != svga->curr.tex_flags.flag_srgb || 221 flag_1d != svga->curr.tex_flags.flag_1d) 222 { 223 svga->dirty |= SVGA_NEW_TEXTURE_FLAGS; 224 svga->curr.tex_flags.flag_1d = flag_1d; 225 svga->curr.tex_flags.flag_srgb = flag_srgb; 226 } 227} 228 229 230 231void svga_init_sampler_functions( struct svga_context *svga ) 232{ 233 svga->pipe.create_sampler_state = svga_create_sampler_state; 234 svga->pipe.bind_sampler_states = svga_bind_sampler_states; 235 svga->pipe.delete_sampler_state = svga_delete_sampler_state; 236 svga->pipe.set_sampler_textures = svga_set_sampler_textures; 237} 238 239 240 241