Path: blob/21.2-virgl/src/gallium/drivers/i915/i915_state_sampler.c
4570 views
/**************************************************************************1*2* Copyright 2003 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627#include "pipe/p_context.h"28#include "pipe/p_state.h"2930#include "i915_context.h"31#include "i915_reg.h"32#include "i915_resource.h"33#include "i915_state.h"34#include "i915_state_inlines.h"3536/*37* A note about min_lod & max_lod.38*39* There is a circular dependancy between the sampler state40* and the map state to be submitted to hw.41*42* Two condition must be meet:43* min_lod =< max_lod == true44* max_lod =< last_level == true45*46*47* This is all fine and dandy if it were for the fact that max_lod48* is set on the map state instead of the sampler state. That is49* the max_lod we submit on map is:50* max_lod = MIN2(last_level, max_lod);51*52* So we need to update the map state when we change samplers and53* we need to change the sampler state when map state is changed.54* The first part is done by calling update_texture in update_samplers55* and the second part is done else where in code tracking the state56* changes.57*/5859/***********************************************************************60* Samplers61*/6263/**64* Compute i915 texture sampling state.65*66* Recalculate all state from scratch. Perhaps not the most67* efficient, but this has gotten complex enough that we need68* something which is understandable and reliable.69* \param state returns the 3 words of compute state70*/71static void72update_sampler(struct i915_context *i915, uint32_t unit,73const struct i915_sampler_state *sampler,74const struct i915_texture *tex, unsigned state[3])75{76const struct pipe_resource *pt = &tex->b;77unsigned minlod, lastlod;7879state[0] = sampler->state[0];80state[1] = sampler->state[1];81state[2] = sampler->state[2];8283if (pt->format == PIPE_FORMAT_UYVY || pt->format == PIPE_FORMAT_YUYV)84state[0] |= SS2_COLORSPACE_CONVERSION;8586if (pt->format == PIPE_FORMAT_B8G8R8A8_SRGB ||87pt->format == PIPE_FORMAT_L8_SRGB) {88state[0] |= SS2_REVERSE_GAMMA_ENABLE;89}9091/* There is no HW support for 1D textures, so we just make them 2D textures92* with h=1, but that means we need to make the Y coordinate not contribute93* to bringing any border color in. Clearing it sets it to WRAP.94*/95if (pt->target == PIPE_TEXTURE_1D) {96state[1] &= ~SS3_TCY_ADDR_MODE_MASK;97}9899/* The GLES2 spec says textures are incomplete (return 0,0,0,1) if:100*101* "A cube map sampler is called, any of the corresponding texture images are102* non-power-of-two images, and either the texture wrap mode is not103* CLAMP_TO_EDGE, or the minification filter is neither NEAREST nor LINEAR."104*105* while the i915 spec says:106*107* "When using cube map texture coordinates, only TEXCOORDMODE_CLAMP and *108* TEXCOORDMODE_CUBE settings are valid, and each TC component must have the109* same Address Control mode. TEXCOORDMODE_CUBE is not valid unless the110* width and height of the cube map are power-of-2."111*112* We don't expose support for the seamless cube map extension, so always use113* edge clamping.114*/115if (pt->target == PIPE_TEXTURE_CUBE) {116state[1] &= ~(SS3_TCX_ADDR_MODE_MASK | SS3_TCY_ADDR_MODE_MASK |117SS3_TCZ_ADDR_MODE_MASK);118state[1] |= (TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT);119state[1] |= (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT);120state[1] |= (TEXCOORDMODE_CLAMP_EDGE << SS3_TCZ_ADDR_MODE_SHIFT);121}122123/* 3D textures don't seem to respect the border color.124* Fallback if there's ever a danger that they might refer to125* it.126*127* Effectively this means fallback on 3D clamp or128* clamp_to_border.129*130* XXX: Check if this is true on i945.131* XXX: Check if this bug got fixed in release silicon.132*/133#if 0134{135const unsigned ws = sampler->templ->wrap_s;136const unsigned wt = sampler->templ->wrap_t;137const unsigned wr = sampler->templ->wrap_r;138if (pt->target == PIPE_TEXTURE_3D &&139(sampler->templ->min_img_filter != PIPE_TEX_FILTER_NEAREST ||140sampler->templ->mag_img_filter != PIPE_TEX_FILTER_NEAREST) &&141(ws == PIPE_TEX_WRAP_CLAMP ||142wt == PIPE_TEX_WRAP_CLAMP ||143wr == PIPE_TEX_WRAP_CLAMP ||144ws == PIPE_TEX_WRAP_CLAMP_TO_BORDER ||145wt == PIPE_TEX_WRAP_CLAMP_TO_BORDER ||146wr == PIPE_TEX_WRAP_CLAMP_TO_BORDER)) {147if (i915->conformance_mode > 0) {148assert(0);149/* sampler->fallback = true; */150/* TODO */151}152}153}154#endif155156/* See note at the top of file */157minlod = sampler->minlod;158lastlod = pt->last_level << 4;159160if (lastlod < minlod) {161minlod = lastlod;162}163164state[1] |= (sampler->minlod << SS3_MIN_LOD_SHIFT);165state[1] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);166}167168/***********************************************************************169* Sampler views170*/171172static uint32_t173translate_texture_format(enum pipe_format pipeFormat,174const struct pipe_sampler_view *view)175{176if ((view->swizzle_r != PIPE_SWIZZLE_X ||177view->swizzle_g != PIPE_SWIZZLE_Y ||178view->swizzle_b != PIPE_SWIZZLE_Z ||179view->swizzle_a != PIPE_SWIZZLE_W) &&180pipeFormat != PIPE_FORMAT_Z24_UNORM_S8_UINT &&181pipeFormat != PIPE_FORMAT_Z24X8_UNORM)182debug_printf("i915: unsupported texture swizzle for format %d\n",183pipeFormat);184185switch (pipeFormat) {186case PIPE_FORMAT_L8_UNORM:187return MAPSURF_8BIT | MT_8BIT_L8;188case PIPE_FORMAT_I8_UNORM:189return MAPSURF_8BIT | MT_8BIT_I8;190case PIPE_FORMAT_A8_UNORM:191return MAPSURF_8BIT | MT_8BIT_A8;192case PIPE_FORMAT_L8A8_UNORM:193return MAPSURF_16BIT | MT_16BIT_AY88;194case PIPE_FORMAT_B5G6R5_UNORM:195return MAPSURF_16BIT | MT_16BIT_RGB565;196case PIPE_FORMAT_B5G5R5A1_UNORM:197return MAPSURF_16BIT | MT_16BIT_ARGB1555;198case PIPE_FORMAT_B4G4R4A4_UNORM:199return MAPSURF_16BIT | MT_16BIT_ARGB4444;200case PIPE_FORMAT_B10G10R10A2_UNORM:201return MAPSURF_32BIT | MT_32BIT_ARGB2101010;202case PIPE_FORMAT_B8G8R8A8_UNORM:203case PIPE_FORMAT_B8G8R8A8_SRGB:204return MAPSURF_32BIT | MT_32BIT_ARGB8888;205case PIPE_FORMAT_B8G8R8X8_UNORM:206return MAPSURF_32BIT | MT_32BIT_XRGB8888;207case PIPE_FORMAT_R8G8B8A8_UNORM:208return MAPSURF_32BIT | MT_32BIT_ABGR8888;209case PIPE_FORMAT_R8G8B8X8_UNORM:210return MAPSURF_32BIT | MT_32BIT_XBGR8888;211case PIPE_FORMAT_YUYV:212return (MAPSURF_422 | MT_422_YCRCB_NORMAL);213case PIPE_FORMAT_UYVY:214return (MAPSURF_422 | MT_422_YCRCB_SWAPY);215#if 0216case PIPE_FORMAT_RGB_FXT1:217case PIPE_FORMAT_RGBA_FXT1:218return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);219#endif220case PIPE_FORMAT_Z16_UNORM:221return (MAPSURF_16BIT | MT_16BIT_L16);222case PIPE_FORMAT_DXT1_RGBA:223case PIPE_FORMAT_DXT1_RGB:224return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);225case PIPE_FORMAT_DXT3_RGBA:226return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);227case PIPE_FORMAT_DXT5_RGBA:228return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);229case PIPE_FORMAT_Z24_UNORM_S8_UINT:230case PIPE_FORMAT_Z24X8_UNORM: {231if (view->swizzle_r == PIPE_SWIZZLE_X &&232view->swizzle_g == PIPE_SWIZZLE_X &&233view->swizzle_b == PIPE_SWIZZLE_X &&234view->swizzle_a == PIPE_SWIZZLE_1)235return (MAPSURF_32BIT | MT_32BIT_xL824);236if (view->swizzle_r == PIPE_SWIZZLE_X &&237view->swizzle_g == PIPE_SWIZZLE_X &&238view->swizzle_b == PIPE_SWIZZLE_X &&239view->swizzle_a == PIPE_SWIZZLE_X)240return (MAPSURF_32BIT | MT_32BIT_xI824);241if (view->swizzle_r == PIPE_SWIZZLE_0 &&242view->swizzle_g == PIPE_SWIZZLE_0 &&243view->swizzle_b == PIPE_SWIZZLE_0 &&244view->swizzle_a == PIPE_SWIZZLE_X)245return (MAPSURF_32BIT | MT_32BIT_xA824);246debug_printf("i915: unsupported depth swizzle %d %d %d %d\n",247view->swizzle_r, view->swizzle_g, view->swizzle_b,248view->swizzle_a);249return (MAPSURF_32BIT | MT_32BIT_xL824);250}251default:252debug_printf("i915: translate_texture_format() bad image format %x\n",253pipeFormat);254assert(0);255return 0;256}257}258259static inline uint32_t260ms3_tiling_bits(enum i915_winsys_buffer_tile tiling)261{262uint32_t tiling_bits = 0;263264switch (tiling) {265case I915_TILE_Y:266tiling_bits |= MS3_TILE_WALK_Y;267FALLTHROUGH;268case I915_TILE_X:269tiling_bits |= MS3_TILED_SURFACE;270FALLTHROUGH;271case I915_TILE_NONE:272break;273}274275return tiling_bits;276}277278static void279update_map(struct i915_context *i915, uint32_t unit,280const struct i915_texture *tex,281const struct i915_sampler_state *sampler,282const struct pipe_sampler_view *view, uint32_t state[3])283{284const struct pipe_resource *pt = &tex->b;285uint32_t width = pt->width0, height = pt->height0, depth = pt->depth0;286int first_level = view->u.tex.first_level;287const uint32_t num_levels = pt->last_level - first_level;288unsigned max_lod = num_levels * 4;289bool is_npot = (!util_is_power_of_two_or_zero(pt->width0) ||290!util_is_power_of_two_or_zero(pt->height0));291uint32_t format, pitch;292293/*294* This is a bit messy. i915 doesn't support NPOT with mipmaps, but we can295* still texture from a single level. This is useful to make u_blitter work.296*/297if (is_npot) {298width = u_minify(width, first_level);299height = u_minify(height, first_level);300max_lod = 1;301}302303assert(tex);304assert(width);305assert(height);306assert(depth);307308format = translate_texture_format(pt->format, view);309pitch = tex->stride;310311assert(format);312assert(pitch);313314/* MS3 state */315state[0] =316(((height - 1) << MS3_HEIGHT_SHIFT) | ((width - 1) << MS3_WIDTH_SHIFT) |317format | ms3_tiling_bits(tex->tiling));318319/*320* XXX When min_filter != mag_filter and there's just one mipmap level,321* set max_lod = 1 to make sure i915 chooses between min/mag filtering.322*/323324/* See note at the top of file */325if (max_lod > (sampler->maxlod >> 2))326max_lod = sampler->maxlod >> 2;327328/* MS4 state */329state[1] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) | MS4_CUBE_FACE_ENA_MASK |330((max_lod) << MS4_MAX_LOD_SHIFT) |331((depth - 1) << MS4_VOLUME_DEPTH_SHIFT));332333if (is_npot)334state[2] = i915_texture_offset(tex, first_level, 0);335else336state[2] = 0;337}338339static void340update_samplers(struct i915_context *i915)341{342uint32_t unit;343344i915->current.sampler_enable_nr = 0;345i915->current.sampler_enable_flags = 0x0;346347for (unit = 0;348unit < i915->num_fragment_sampler_views && unit < i915->num_samplers;349unit++) {350/* determine unit enable/disable by looking for a bound texture */351/* could also examine the fragment program? */352if (i915->fragment_sampler_views[unit]) {353struct i915_texture *texture =354i915_texture(i915->fragment_sampler_views[unit]->texture);355356update_sampler(i915, unit,357i915->fragment_sampler[unit], /* sampler state */358texture, /* texture */359i915->current.sampler[unit]); /* the result */360update_map(i915, unit, texture, /* texture */361i915->fragment_sampler[unit], /* sampler state */362i915->fragment_sampler_views[unit], /* sampler view */363i915->current.texbuffer[unit]); /* the result */364365i915->current.sampler_enable_nr++;366i915->current.sampler_enable_flags |= (1 << unit);367}368}369370i915->hardware_dirty |= I915_HW_SAMPLER | I915_HW_MAP;371}372373struct i915_tracked_state i915_hw_samplers = {374"samplers", update_samplers, I915_NEW_SAMPLER | I915_NEW_SAMPLER_VIEW};375376377