Path: blob/21.2-virgl/src/gallium/drivers/r300/r300_texture.c
4570 views
/*1* Copyright 2008 Corbin Simpson <[email protected]>2* Copyright 2010 Marek Olšák <[email protected]>3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* on the rights to use, copy, modify, merge, publish, distribute, sub8* license, and/or sell copies of the Software, and to permit persons to whom9* the Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL18* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,19* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR20* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE21* USE OR OTHER DEALINGS IN THE SOFTWARE. */2223/* Always include headers in the reverse order!! ~ M. */24#include "r300_texture.h"2526#include "r300_context.h"27#include "r300_reg.h"28#include "r300_texture_desc.h"29#include "r300_transfer.h"30#include "r300_screen.h"3132#include "util/format/u_format.h"33#include "util/format/u_format_s3tc.h"34#include "util/u_math.h"35#include "util/u_memory.h"3637#include "pipe/p_screen.h"38#include "frontend/winsys_handle.h"3940/* These formats are supported by swapping their bytes.41* The swizzles must be set exactly like their non-swapped counterparts,42* because byte-swapping is what reverses the component order, not swizzling.43*44* This function returns the format that must be used to program CB and TX45* swizzles.46*/47static enum pipe_format r300_unbyteswap_array_format(enum pipe_format format)48{49/* FIXME: Disabled on little endian because of a reported regression:50* https://bugs.freedesktop.org/show_bug.cgi?id=98869 */51if (PIPE_ENDIAN_NATIVE != PIPE_ENDIAN_BIG)52return format;5354/* Only BGRA 8888 array formats are supported for simplicity of55* the implementation. */56switch (format) {57case PIPE_FORMAT_A8R8G8B8_UNORM:58return PIPE_FORMAT_B8G8R8A8_UNORM;59case PIPE_FORMAT_A8R8G8B8_SRGB:60return PIPE_FORMAT_B8G8R8A8_SRGB;61case PIPE_FORMAT_X8R8G8B8_UNORM:62return PIPE_FORMAT_B8G8R8X8_UNORM;63case PIPE_FORMAT_X8R8G8B8_SRGB:64return PIPE_FORMAT_B8G8R8X8_SRGB;65default:66return format;67}68}6970static unsigned r300_get_endian_swap(enum pipe_format format)71{72const struct util_format_description *desc;73unsigned swap_size;7475if (r300_unbyteswap_array_format(format) != format)76return R300_SURF_DWORD_SWAP;7778if (PIPE_ENDIAN_NATIVE != PIPE_ENDIAN_BIG)79return R300_SURF_NO_SWAP;8081desc = util_format_description(format);82if (!desc)83return R300_SURF_NO_SWAP;8485/* Compressed formats should be in the little endian format. */86if (desc->block.width != 1 || desc->block.height != 1)87return R300_SURF_NO_SWAP;8889swap_size = desc->is_array ? desc->channel[0].size : desc->block.bits;9091switch (swap_size) {92default: /* shouldn't happen? */93case 8:94return R300_SURF_NO_SWAP;95case 16:96return R300_SURF_WORD_SWAP;97case 32:98return R300_SURF_DWORD_SWAP;99}100}101102unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,103const unsigned char *swizzle_view,104boolean dxtc_swizzle)105{106unsigned i;107unsigned char swizzle[4];108unsigned result = 0;109const uint32_t swizzle_shift[4] = {110R300_TX_FORMAT_R_SHIFT,111R300_TX_FORMAT_G_SHIFT,112R300_TX_FORMAT_B_SHIFT,113R300_TX_FORMAT_A_SHIFT114};115uint32_t swizzle_bit[4] = {116dxtc_swizzle ? R300_TX_FORMAT_Z : R300_TX_FORMAT_X,117R300_TX_FORMAT_Y,118dxtc_swizzle ? R300_TX_FORMAT_X : R300_TX_FORMAT_Z,119R300_TX_FORMAT_W120};121122if (swizzle_view) {123/* Combine two sets of swizzles. */124util_format_compose_swizzles(swizzle_format, swizzle_view, swizzle);125} else {126memcpy(swizzle, swizzle_format, 4);127}128129/* Get swizzle. */130for (i = 0; i < 4; i++) {131switch (swizzle[i]) {132case PIPE_SWIZZLE_Y:133result |= swizzle_bit[1] << swizzle_shift[i];134break;135case PIPE_SWIZZLE_Z:136result |= swizzle_bit[2] << swizzle_shift[i];137break;138case PIPE_SWIZZLE_W:139result |= swizzle_bit[3] << swizzle_shift[i];140break;141case PIPE_SWIZZLE_0:142result |= R300_TX_FORMAT_ZERO << swizzle_shift[i];143break;144case PIPE_SWIZZLE_1:145result |= R300_TX_FORMAT_ONE << swizzle_shift[i];146break;147default: /* PIPE_SWIZZLE_X */148result |= swizzle_bit[0] << swizzle_shift[i];149}150}151return result;152}153154/* Translate a pipe_format into a useful texture format for sampling.155*156* Some special formats are translated directly using R300_EASY_TX_FORMAT,157* but the majority of them is translated in a generic way, automatically158* supporting all the formats hw can support.159*160* R300_EASY_TX_FORMAT swizzles the texture.161* Note the signature of R300_EASY_TX_FORMAT:162* R300_EASY_TX_FORMAT(B, G, R, A, FORMAT);163*164* The FORMAT specifies how the texture sampler will treat the texture, and165* makes available X, Y, Z, W, ZERO, and ONE for swizzling. */166uint32_t r300_translate_texformat(enum pipe_format format,167const unsigned char *swizzle_view,168boolean is_r500,169boolean dxtc_swizzle)170{171uint32_t result = 0;172const struct util_format_description *desc;173unsigned i;174boolean uniform = TRUE;175const uint32_t sign_bit[4] = {176R300_TX_FORMAT_SIGNED_W,177R300_TX_FORMAT_SIGNED_Z,178R300_TX_FORMAT_SIGNED_Y,179R300_TX_FORMAT_SIGNED_X,180};181182format = r300_unbyteswap_array_format(format);183desc = util_format_description(format);184185/* Colorspace (return non-RGB formats directly). */186switch (desc->colorspace) {187/* Depth stencil formats.188* Swizzles are added in r300_merge_textures_and_samplers. */189case UTIL_FORMAT_COLORSPACE_ZS:190switch (format) {191case PIPE_FORMAT_Z16_UNORM:192return R300_TX_FORMAT_X16;193case PIPE_FORMAT_X8Z24_UNORM:194case PIPE_FORMAT_S8_UINT_Z24_UNORM:195if (is_r500)196return R500_TX_FORMAT_Y8X24;197else198return R300_TX_FORMAT_Y16X16;199default:200return ~0; /* Unsupported. */201}202203/* YUV formats. */204case UTIL_FORMAT_COLORSPACE_YUV:205result |= R300_TX_FORMAT_YUV_TO_RGB;206207switch (format) {208case PIPE_FORMAT_UYVY:209return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result;210case PIPE_FORMAT_YUYV:211return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result;212default:213return ~0; /* Unsupported/unknown. */214}215216/* Add gamma correction. */217case UTIL_FORMAT_COLORSPACE_SRGB:218result |= R300_TX_FORMAT_GAMMA;219break;220221default:222switch (format) {223/* Same as YUV but without the YUR->RGB conversion. */224case PIPE_FORMAT_R8G8_B8G8_UNORM:225return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result;226case PIPE_FORMAT_G8R8_G8B8_UNORM:227return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result;228default:;229}230}231232/* Add swizzling. */233/* The RGTC1_SNORM and LATC1_SNORM swizzle is done in the shader. */234if (util_format_is_compressed(format) &&235dxtc_swizzle &&236format != PIPE_FORMAT_RGTC2_UNORM &&237format != PIPE_FORMAT_RGTC2_SNORM &&238format != PIPE_FORMAT_LATC2_UNORM &&239format != PIPE_FORMAT_LATC2_SNORM &&240format != PIPE_FORMAT_RGTC1_UNORM &&241format != PIPE_FORMAT_RGTC1_SNORM &&242format != PIPE_FORMAT_LATC1_UNORM &&243format != PIPE_FORMAT_LATC1_SNORM) {244result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view,245TRUE);246} else {247result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view,248FALSE);249}250251/* S3TC formats. */252if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {253switch (format) {254case PIPE_FORMAT_DXT1_RGB:255case PIPE_FORMAT_DXT1_RGBA:256case PIPE_FORMAT_DXT1_SRGB:257case PIPE_FORMAT_DXT1_SRGBA:258return R300_TX_FORMAT_DXT1 | result;259case PIPE_FORMAT_DXT3_RGBA:260case PIPE_FORMAT_DXT3_SRGBA:261return R300_TX_FORMAT_DXT3 | result;262case PIPE_FORMAT_DXT5_RGBA:263case PIPE_FORMAT_DXT5_SRGBA:264return R300_TX_FORMAT_DXT5 | result;265default:266return ~0; /* Unsupported/unknown. */267}268}269270/* RGTC formats. */271if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {272switch (format) {273case PIPE_FORMAT_RGTC1_SNORM:274case PIPE_FORMAT_LATC1_SNORM:275result |= sign_bit[0];276FALLTHROUGH;277case PIPE_FORMAT_LATC1_UNORM:278case PIPE_FORMAT_RGTC1_UNORM:279return R500_TX_FORMAT_ATI1N | result;280281case PIPE_FORMAT_RGTC2_SNORM:282case PIPE_FORMAT_LATC2_SNORM:283result |= sign_bit[1] | sign_bit[0];284FALLTHROUGH;285case PIPE_FORMAT_RGTC2_UNORM:286case PIPE_FORMAT_LATC2_UNORM:287return R400_TX_FORMAT_ATI2N | result;288289default:290return ~0; /* Unsupported/unknown. */291}292}293294/* This is truly a special format.295* It stores R8G8 and B is computed using sqrt(1 - R^2 - G^2)296* in the sampler unit. Also known as D3DFMT_CxV8U8. */297if (format == PIPE_FORMAT_R8G8Bx_SNORM) {298return R300_TX_FORMAT_CxV8U8 | result;299}300301/* Integer and fixed-point 16.16 textures are not supported. */302for (i = 0; i < 4; i++) {303if (desc->channel[i].type == UTIL_FORMAT_TYPE_FIXED ||304((desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED ||305desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) &&306(!desc->channel[i].normalized ||307desc->channel[i].pure_integer))) {308return ~0; /* Unsupported/unknown. */309}310}311312/* Add sign. */313for (i = 0; i < desc->nr_channels; i++) {314if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {315result |= sign_bit[i];316}317}318319/* See whether the components are of the same size. */320for (i = 1; i < desc->nr_channels; i++) {321uniform = uniform && desc->channel[0].size == desc->channel[i].size;322}323324/* Non-uniform formats. */325if (!uniform) {326switch (desc->nr_channels) {327case 3:328if (desc->channel[0].size == 5 &&329desc->channel[1].size == 6 &&330desc->channel[2].size == 5) {331return R300_TX_FORMAT_Z5Y6X5 | result;332}333if (desc->channel[0].size == 5 &&334desc->channel[1].size == 5 &&335desc->channel[2].size == 6) {336return R300_TX_FORMAT_Z6Y5X5 | result;337}338if (desc->channel[0].size == 2 &&339desc->channel[1].size == 3 &&340desc->channel[2].size == 3) {341return R300_TX_FORMAT_Z3Y3X2 | result;342}343return ~0; /* Unsupported/unknown. */344345case 4:346if (desc->channel[0].size == 5 &&347desc->channel[1].size == 5 &&348desc->channel[2].size == 5 &&349desc->channel[3].size == 1) {350return R300_TX_FORMAT_W1Z5Y5X5 | result;351}352if (desc->channel[0].size == 10 &&353desc->channel[1].size == 10 &&354desc->channel[2].size == 10 &&355desc->channel[3].size == 2) {356return R300_TX_FORMAT_W2Z10Y10X10 | result;357}358}359return ~0; /* Unsupported/unknown. */360}361362/* Find the first non-VOID channel. */363for (i = 0; i < 4; i++) {364if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {365break;366}367}368369if (i == 4)370return ~0; /* Unsupported/unknown. */371372/* And finally, uniform formats. */373switch (desc->channel[i].type) {374case UTIL_FORMAT_TYPE_UNSIGNED:375case UTIL_FORMAT_TYPE_SIGNED:376if (!desc->channel[i].normalized &&377desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {378return ~0;379}380381switch (desc->channel[i].size) {382case 4:383switch (desc->nr_channels) {384case 2:385return R300_TX_FORMAT_Y4X4 | result;386case 4:387return R300_TX_FORMAT_W4Z4Y4X4 | result;388}389return ~0;390391case 8:392switch (desc->nr_channels) {393case 1:394return R300_TX_FORMAT_X8 | result;395case 2:396return R300_TX_FORMAT_Y8X8 | result;397case 4:398return R300_TX_FORMAT_W8Z8Y8X8 | result;399}400return ~0;401402case 16:403switch (desc->nr_channels) {404case 1:405return R300_TX_FORMAT_X16 | result;406case 2:407return R300_TX_FORMAT_Y16X16 | result;408case 4:409return R300_TX_FORMAT_W16Z16Y16X16 | result;410}411}412return ~0;413414case UTIL_FORMAT_TYPE_FLOAT:415switch (desc->channel[i].size) {416case 16:417switch (desc->nr_channels) {418case 1:419return R300_TX_FORMAT_16F | result;420case 2:421return R300_TX_FORMAT_16F_16F | result;422case 4:423return R300_TX_FORMAT_16F_16F_16F_16F | result;424}425return ~0;426427case 32:428switch (desc->nr_channels) {429case 1:430return R300_TX_FORMAT_32F | result;431case 2:432return R300_TX_FORMAT_32F_32F | result;433case 4:434return R300_TX_FORMAT_32F_32F_32F_32F | result;435}436}437}438439return ~0; /* Unsupported/unknown. */440}441442uint32_t r500_tx_format_msb_bit(enum pipe_format format)443{444switch (format) {445case PIPE_FORMAT_RGTC1_UNORM:446case PIPE_FORMAT_RGTC1_SNORM:447case PIPE_FORMAT_LATC1_UNORM:448case PIPE_FORMAT_LATC1_SNORM:449case PIPE_FORMAT_X8Z24_UNORM:450case PIPE_FORMAT_S8_UINT_Z24_UNORM:451return R500_TXFORMAT_MSB;452default:453return 0;454}455}456457/* Buffer formats. */458459/* Colorbuffer formats. This is the unswizzled format of the RB3D block's460* output. For the swizzling of the targets, check the shader's format. */461static uint32_t r300_translate_colorformat(enum pipe_format format)462{463format = r300_unbyteswap_array_format(format);464465switch (format) {466/* 8-bit buffers. */467case PIPE_FORMAT_A8_UNORM:468case PIPE_FORMAT_A8_SNORM:469case PIPE_FORMAT_I8_UNORM:470case PIPE_FORMAT_I8_SNORM:471case PIPE_FORMAT_L8_UNORM:472case PIPE_FORMAT_L8_SNORM:473case PIPE_FORMAT_R8_UNORM:474case PIPE_FORMAT_R8_SNORM:475return R300_COLOR_FORMAT_I8;476477/* 16-bit buffers. */478case PIPE_FORMAT_L8A8_UNORM:479case PIPE_FORMAT_L8A8_SNORM:480case PIPE_FORMAT_R8G8_UNORM:481case PIPE_FORMAT_R8G8_SNORM:482case PIPE_FORMAT_R8A8_UNORM:483case PIPE_FORMAT_R8A8_SNORM:484/* These formats work fine with UV88 if US_OUT_FMT is set correctly. */485case PIPE_FORMAT_A16_UNORM:486case PIPE_FORMAT_A16_SNORM:487case PIPE_FORMAT_A16_FLOAT:488case PIPE_FORMAT_L16_UNORM:489case PIPE_FORMAT_L16_SNORM:490case PIPE_FORMAT_L16_FLOAT:491case PIPE_FORMAT_I16_UNORM:492case PIPE_FORMAT_I16_SNORM:493case PIPE_FORMAT_I16_FLOAT:494case PIPE_FORMAT_R16_UNORM:495case PIPE_FORMAT_R16_SNORM:496case PIPE_FORMAT_R16_FLOAT:497return R300_COLOR_FORMAT_UV88;498499case PIPE_FORMAT_B5G6R5_UNORM:500return R300_COLOR_FORMAT_RGB565;501502case PIPE_FORMAT_B5G5R5A1_UNORM:503case PIPE_FORMAT_B5G5R5X1_UNORM:504return R300_COLOR_FORMAT_ARGB1555;505506case PIPE_FORMAT_B4G4R4A4_UNORM:507case PIPE_FORMAT_B4G4R4X4_UNORM:508return R300_COLOR_FORMAT_ARGB4444;509510/* 32-bit buffers. */511case PIPE_FORMAT_B8G8R8A8_UNORM:512/*case PIPE_FORMAT_B8G8R8A8_SNORM:*/513case PIPE_FORMAT_B8G8R8X8_UNORM:514/*case PIPE_FORMAT_B8G8R8X8_SNORM:*/515case PIPE_FORMAT_R8G8B8A8_UNORM:516case PIPE_FORMAT_R8G8B8A8_SNORM:517case PIPE_FORMAT_R8G8B8X8_UNORM:518case PIPE_FORMAT_R8G8B8X8_SNORM:519/* These formats work fine with ARGB8888 if US_OUT_FMT is set520* correctly. */521case PIPE_FORMAT_R16G16_UNORM:522case PIPE_FORMAT_R16G16_SNORM:523case PIPE_FORMAT_R16G16_FLOAT:524case PIPE_FORMAT_L16A16_UNORM:525case PIPE_FORMAT_L16A16_SNORM:526case PIPE_FORMAT_L16A16_FLOAT:527case PIPE_FORMAT_R16A16_UNORM:528case PIPE_FORMAT_R16A16_SNORM:529case PIPE_FORMAT_R16A16_FLOAT:530case PIPE_FORMAT_A32_FLOAT:531case PIPE_FORMAT_L32_FLOAT:532case PIPE_FORMAT_I32_FLOAT:533case PIPE_FORMAT_R32_FLOAT:534return R300_COLOR_FORMAT_ARGB8888;535536case PIPE_FORMAT_R10G10B10A2_UNORM:537case PIPE_FORMAT_R10G10B10X2_SNORM:538case PIPE_FORMAT_B10G10R10A2_UNORM:539case PIPE_FORMAT_B10G10R10X2_UNORM:540return R500_COLOR_FORMAT_ARGB2101010; /* R5xx-only? */541542/* 64-bit buffers. */543case PIPE_FORMAT_R16G16B16A16_UNORM:544case PIPE_FORMAT_R16G16B16A16_SNORM:545case PIPE_FORMAT_R16G16B16A16_FLOAT:546case PIPE_FORMAT_R16G16B16X16_UNORM:547case PIPE_FORMAT_R16G16B16X16_SNORM:548case PIPE_FORMAT_R16G16B16X16_FLOAT:549/* These formats work fine with ARGB16161616 if US_OUT_FMT is set550* correctly. */551case PIPE_FORMAT_R32G32_FLOAT:552case PIPE_FORMAT_L32A32_FLOAT:553case PIPE_FORMAT_R32A32_FLOAT:554return R300_COLOR_FORMAT_ARGB16161616;555556/* 128-bit buffers. */557case PIPE_FORMAT_R32G32B32A32_FLOAT:558case PIPE_FORMAT_R32G32B32X32_FLOAT:559return R300_COLOR_FORMAT_ARGB32323232;560561/* YUV buffers. */562case PIPE_FORMAT_UYVY:563return R300_COLOR_FORMAT_YVYU;564case PIPE_FORMAT_YUYV:565return R300_COLOR_FORMAT_VYUY;566default:567return ~0; /* Unsupported. */568}569}570571/* Depthbuffer and stencilbuffer. Thankfully, we only support two flavors. */572static uint32_t r300_translate_zsformat(enum pipe_format format)573{574switch (format) {575/* 16-bit depth, no stencil */576case PIPE_FORMAT_Z16_UNORM:577return R300_DEPTHFORMAT_16BIT_INT_Z;578/* 24-bit depth, ignored stencil */579case PIPE_FORMAT_X8Z24_UNORM:580/* 24-bit depth, 8-bit stencil */581case PIPE_FORMAT_S8_UINT_Z24_UNORM:582return R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;583default:584return ~0; /* Unsupported. */585}586}587588/* Shader output formats. This is essentially the swizzle from the shader589* to the RB3D block.590*591* Note that formats are stored from C3 to C0. */592static uint32_t r300_translate_out_fmt(enum pipe_format format)593{594uint32_t modifier = 0;595unsigned i;596const struct util_format_description *desc;597boolean uniform_sign;598599format = r300_unbyteswap_array_format(format);600desc = util_format_description(format);601602/* Find the first non-VOID channel. */603for (i = 0; i < 4; i++) {604if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {605break;606}607}608609if (i == 4)610return ~0; /* Unsupported/unknown. */611612/* Specifies how the shader output is written to the fog unit. */613switch (desc->channel[i].type) {614case UTIL_FORMAT_TYPE_FLOAT:615switch (desc->channel[i].size) {616case 32:617switch (desc->nr_channels) {618case 1:619modifier |= R300_US_OUT_FMT_C_32_FP;620break;621case 2:622modifier |= R300_US_OUT_FMT_C2_32_FP;623break;624case 4:625modifier |= R300_US_OUT_FMT_C4_32_FP;626break;627}628break;629630case 16:631switch (desc->nr_channels) {632case 1:633modifier |= R300_US_OUT_FMT_C_16_FP;634break;635case 2:636modifier |= R300_US_OUT_FMT_C2_16_FP;637break;638case 4:639modifier |= R300_US_OUT_FMT_C4_16_FP;640break;641}642break;643}644break;645646default:647switch (desc->channel[i].size) {648case 16:649switch (desc->nr_channels) {650case 1:651modifier |= R300_US_OUT_FMT_C_16;652break;653case 2:654modifier |= R300_US_OUT_FMT_C2_16;655break;656case 4:657modifier |= R300_US_OUT_FMT_C4_16;658break;659}660break;661662case 10:663modifier |= R300_US_OUT_FMT_C4_10;664break;665666default:667/* C4_8 seems to be used for the formats whose pixel size668* is <= 32 bits. */669modifier |= R300_US_OUT_FMT_C4_8;670break;671}672}673674/* Add sign. */675uniform_sign = TRUE;676for (i = 0; i < desc->nr_channels; i++)677if (desc->channel[i].type != UTIL_FORMAT_TYPE_SIGNED)678uniform_sign = FALSE;679680if (uniform_sign)681modifier |= R300_OUT_SIGN(0xf);682683/* Add swizzles and return. */684switch (format) {685/*** Special cases (non-standard channel mapping) ***/686687/* X8688* COLORFORMAT_I8 stores the Z component (C2). */689case PIPE_FORMAT_A8_UNORM:690case PIPE_FORMAT_A8_SNORM:691return modifier | R300_C2_SEL_A;692case PIPE_FORMAT_I8_UNORM:693case PIPE_FORMAT_I8_SNORM:694case PIPE_FORMAT_L8_UNORM:695case PIPE_FORMAT_L8_SNORM:696case PIPE_FORMAT_R8_UNORM:697case PIPE_FORMAT_R8_SNORM:698return modifier | R300_C2_SEL_R;699700/* X8Y8701* COLORFORMAT_UV88 stores ZX (C2 and C0). */702case PIPE_FORMAT_L8A8_SNORM:703case PIPE_FORMAT_L8A8_UNORM:704case PIPE_FORMAT_R8A8_SNORM:705case PIPE_FORMAT_R8A8_UNORM:706return modifier | R300_C0_SEL_A | R300_C2_SEL_R;707case PIPE_FORMAT_R8G8_SNORM:708case PIPE_FORMAT_R8G8_UNORM:709return modifier | R300_C0_SEL_G | R300_C2_SEL_R;710711/* X32Y32712* ARGB16161616 stores XZ for RG32F */713case PIPE_FORMAT_R32G32_FLOAT:714return modifier | R300_C0_SEL_R | R300_C2_SEL_G;715716/*** Generic cases (standard channel mapping) ***/717718/* BGRA outputs. */719case PIPE_FORMAT_B5G6R5_UNORM:720case PIPE_FORMAT_B5G5R5A1_UNORM:721case PIPE_FORMAT_B5G5R5X1_UNORM:722case PIPE_FORMAT_B4G4R4A4_UNORM:723case PIPE_FORMAT_B4G4R4X4_UNORM:724case PIPE_FORMAT_B8G8R8A8_UNORM:725/*case PIPE_FORMAT_B8G8R8A8_SNORM:*/726case PIPE_FORMAT_B8G8R8X8_UNORM:727/*case PIPE_FORMAT_B8G8R8X8_SNORM:*/728case PIPE_FORMAT_B10G10R10A2_UNORM:729case PIPE_FORMAT_B10G10R10X2_UNORM:730return modifier |731R300_C0_SEL_B | R300_C1_SEL_G |732R300_C2_SEL_R | R300_C3_SEL_A;733734/* ARGB outputs. */735case PIPE_FORMAT_A16_UNORM:736case PIPE_FORMAT_A16_SNORM:737case PIPE_FORMAT_A16_FLOAT:738case PIPE_FORMAT_A32_FLOAT:739return modifier |740R300_C0_SEL_A | R300_C1_SEL_R |741R300_C2_SEL_G | R300_C3_SEL_B;742743/* RGBA outputs. */744case PIPE_FORMAT_R8G8B8X8_UNORM:745case PIPE_FORMAT_R8G8B8X8_SNORM:746case PIPE_FORMAT_R8G8B8A8_UNORM:747case PIPE_FORMAT_R8G8B8A8_SNORM:748case PIPE_FORMAT_R10G10B10A2_UNORM:749case PIPE_FORMAT_R10G10B10X2_SNORM:750case PIPE_FORMAT_R16_UNORM:751case PIPE_FORMAT_R16G16_UNORM:752case PIPE_FORMAT_R16G16B16A16_UNORM:753case PIPE_FORMAT_R16_SNORM:754case PIPE_FORMAT_R16G16_SNORM:755case PIPE_FORMAT_R16G16B16A16_SNORM:756case PIPE_FORMAT_R16_FLOAT:757case PIPE_FORMAT_R16G16_FLOAT:758case PIPE_FORMAT_R16G16B16A16_FLOAT:759case PIPE_FORMAT_R32_FLOAT:760case PIPE_FORMAT_R32G32B32A32_FLOAT:761case PIPE_FORMAT_R32G32B32X32_FLOAT:762case PIPE_FORMAT_L16_UNORM:763case PIPE_FORMAT_L16_SNORM:764case PIPE_FORMAT_L16_FLOAT:765case PIPE_FORMAT_L32_FLOAT:766case PIPE_FORMAT_I16_UNORM:767case PIPE_FORMAT_I16_SNORM:768case PIPE_FORMAT_I16_FLOAT:769case PIPE_FORMAT_I32_FLOAT:770case PIPE_FORMAT_R16G16B16X16_UNORM:771case PIPE_FORMAT_R16G16B16X16_SNORM:772case PIPE_FORMAT_R16G16B16X16_FLOAT:773return modifier |774R300_C0_SEL_R | R300_C1_SEL_G |775R300_C2_SEL_B | R300_C3_SEL_A;776777/* LA outputs. */778case PIPE_FORMAT_L16A16_UNORM:779case PIPE_FORMAT_L16A16_SNORM:780case PIPE_FORMAT_L16A16_FLOAT:781case PIPE_FORMAT_R16A16_UNORM:782case PIPE_FORMAT_R16A16_SNORM:783case PIPE_FORMAT_R16A16_FLOAT:784case PIPE_FORMAT_L32A32_FLOAT:785case PIPE_FORMAT_R32A32_FLOAT:786return modifier |787R300_C0_SEL_R | R300_C1_SEL_A;788789default:790return ~0; /* Unsupported. */791}792}793794static uint32_t r300_translate_colormask_swizzle(enum pipe_format format)795{796format = r300_unbyteswap_array_format(format);797798switch (format) {799case PIPE_FORMAT_A8_UNORM:800case PIPE_FORMAT_A8_SNORM:801case PIPE_FORMAT_A16_UNORM:802case PIPE_FORMAT_A16_SNORM:803case PIPE_FORMAT_A16_FLOAT:804case PIPE_FORMAT_A32_FLOAT:805return COLORMASK_AAAA;806807case PIPE_FORMAT_I8_UNORM:808case PIPE_FORMAT_I8_SNORM:809case PIPE_FORMAT_L8_UNORM:810case PIPE_FORMAT_L8_SNORM:811case PIPE_FORMAT_R8_UNORM:812case PIPE_FORMAT_R8_SNORM:813case PIPE_FORMAT_R32_FLOAT:814case PIPE_FORMAT_L32_FLOAT:815case PIPE_FORMAT_I32_FLOAT:816return COLORMASK_RRRR;817818case PIPE_FORMAT_L8A8_SNORM:819case PIPE_FORMAT_L8A8_UNORM:820case PIPE_FORMAT_R8A8_UNORM:821case PIPE_FORMAT_R8A8_SNORM:822case PIPE_FORMAT_L16A16_UNORM:823case PIPE_FORMAT_L16A16_SNORM:824case PIPE_FORMAT_L16A16_FLOAT:825case PIPE_FORMAT_R16A16_UNORM:826case PIPE_FORMAT_R16A16_SNORM:827case PIPE_FORMAT_R16A16_FLOAT:828case PIPE_FORMAT_L32A32_FLOAT:829case PIPE_FORMAT_R32A32_FLOAT:830return COLORMASK_ARRA;831832case PIPE_FORMAT_R8G8_SNORM:833case PIPE_FORMAT_R8G8_UNORM:834case PIPE_FORMAT_R16G16_UNORM:835case PIPE_FORMAT_R16G16_SNORM:836case PIPE_FORMAT_R16G16_FLOAT:837case PIPE_FORMAT_R32G32_FLOAT:838return COLORMASK_GRRG;839840case PIPE_FORMAT_B5G5R5X1_UNORM:841case PIPE_FORMAT_B4G4R4X4_UNORM:842case PIPE_FORMAT_B8G8R8X8_UNORM:843/*case PIPE_FORMAT_B8G8R8X8_SNORM:*/844case PIPE_FORMAT_B10G10R10X2_UNORM:845return COLORMASK_BGRX;846847case PIPE_FORMAT_B5G6R5_UNORM:848case PIPE_FORMAT_B5G5R5A1_UNORM:849case PIPE_FORMAT_B4G4R4A4_UNORM:850case PIPE_FORMAT_B8G8R8A8_UNORM:851/*case PIPE_FORMAT_B8G8R8A8_SNORM:*/852case PIPE_FORMAT_B10G10R10A2_UNORM:853return COLORMASK_BGRA;854855case PIPE_FORMAT_R8G8B8X8_UNORM:856/* RGBX_SNORM formats are broken for an unknown reason */857/*case PIPE_FORMAT_R8G8B8X8_SNORM:*/858/*case PIPE_FORMAT_R10G10B10X2_SNORM:*/859case PIPE_FORMAT_R16G16B16X16_UNORM:860/*case PIPE_FORMAT_R16G16B16X16_SNORM:*/861case PIPE_FORMAT_R16G16B16X16_FLOAT:862case PIPE_FORMAT_R32G32B32X32_FLOAT:863return COLORMASK_RGBX;864865case PIPE_FORMAT_R8G8B8A8_UNORM:866case PIPE_FORMAT_R8G8B8A8_SNORM:867case PIPE_FORMAT_R10G10B10A2_UNORM:868case PIPE_FORMAT_R16_UNORM:869case PIPE_FORMAT_R16G16B16A16_UNORM:870case PIPE_FORMAT_R16_SNORM:871case PIPE_FORMAT_R16G16B16A16_SNORM:872case PIPE_FORMAT_R16_FLOAT:873case PIPE_FORMAT_R16G16B16A16_FLOAT:874case PIPE_FORMAT_R32G32B32A32_FLOAT:875case PIPE_FORMAT_L16_UNORM:876case PIPE_FORMAT_L16_SNORM:877case PIPE_FORMAT_L16_FLOAT:878case PIPE_FORMAT_I16_UNORM:879case PIPE_FORMAT_I16_SNORM:880case PIPE_FORMAT_I16_FLOAT:881return COLORMASK_RGBA;882883default:884return ~0; /* Unsupported. */885}886}887888boolean r300_is_colorbuffer_format_supported(enum pipe_format format)889{890return r300_translate_colorformat(format) != ~0 &&891r300_translate_out_fmt(format) != ~0 &&892r300_translate_colormask_swizzle(format) != ~0;893}894895boolean r300_is_zs_format_supported(enum pipe_format format)896{897return r300_translate_zsformat(format) != ~0;898}899900boolean r300_is_sampler_format_supported(enum pipe_format format)901{902return r300_translate_texformat(format, 0, TRUE, FALSE) != ~0;903}904905void r300_texture_setup_format_state(struct r300_screen *screen,906struct r300_resource *tex,907enum pipe_format format,908unsigned level,909unsigned width0_override,910unsigned height0_override,911struct r300_texture_format_state *out)912{913struct pipe_resource *pt = &tex->b;914struct r300_texture_desc *desc = &tex->tex;915boolean is_r500 = screen->caps.is_r500;916unsigned width, height, depth;917unsigned txwidth, txheight, txdepth;918919width = u_minify(width0_override, level);920height = u_minify(height0_override, level);921depth = u_minify(desc->depth0, level);922923txwidth = (width - 1) & 0x7ff;924txheight = (height - 1) & 0x7ff;925txdepth = util_logbase2(depth) & 0xf;926927/* Mask out all the fields we change. */928out->format0 = 0;929out->format1 &= ~R300_TX_FORMAT_TEX_COORD_TYPE_MASK;930out->format2 &= R500_TXFORMAT_MSB;931out->tile_config = 0;932933/* Set sampler state. */934out->format0 =935R300_TX_WIDTH(txwidth) |936R300_TX_HEIGHT(txheight) |937R300_TX_DEPTH(txdepth);938939if (desc->uses_stride_addressing) {940unsigned stride =941r300_stride_to_width(format, desc->stride_in_bytes[level]);942/* rectangles love this */943out->format0 |= R300_TX_PITCH_EN;944out->format2 = (stride - 1) & 0x1fff;945}946947if (pt->target == PIPE_TEXTURE_CUBE) {948out->format1 |= R300_TX_FORMAT_CUBIC_MAP;949}950if (pt->target == PIPE_TEXTURE_3D) {951out->format1 |= R300_TX_FORMAT_3D;952}953954/* large textures on r500 */955if (is_r500)956{957unsigned us_width = txwidth;958unsigned us_height = txheight;959unsigned us_depth = txdepth;960961if (width > 2048) {962out->format2 |= R500_TXWIDTH_BIT11;963}964if (height > 2048) {965out->format2 |= R500_TXHEIGHT_BIT11;966}967968/* The US_FORMAT register fixes an R500 TX addressing bug.969* Don't ask why it must be set like this. I don't know it either. */970if (width > 2048) {971us_width = (0x000007FF + us_width) >> 1;972us_depth |= 0x0000000D;973}974if (height > 2048) {975us_height = (0x000007FF + us_height) >> 1;976us_depth |= 0x0000000E;977}978979out->us_format0 =980R300_TX_WIDTH(us_width) |981R300_TX_HEIGHT(us_height) |982R300_TX_DEPTH(us_depth);983}984985out->tile_config = R300_TXO_MACRO_TILE(desc->macrotile[level]) |986R300_TXO_MICRO_TILE(desc->microtile) |987R300_TXO_ENDIAN(r300_get_endian_swap(format));988}989990static void r300_texture_setup_fb_state(struct r300_surface *surf)991{992struct r300_resource *tex = r300_resource(surf->base.texture);993unsigned level = surf->base.u.tex.level;994unsigned stride =995r300_stride_to_width(surf->base.format, tex->tex.stride_in_bytes[level]);996997/* Set framebuffer state. */998if (util_format_is_depth_or_stencil(surf->base.format)) {999surf->pitch =1000stride |1001R300_DEPTHMACROTILE(tex->tex.macrotile[level]) |1002R300_DEPTHMICROTILE(tex->tex.microtile) |1003R300_DEPTHENDIAN(r300_get_endian_swap(surf->base.format));1004surf->format = r300_translate_zsformat(surf->base.format);1005surf->pitch_zmask = tex->tex.zmask_stride_in_pixels[level];1006surf->pitch_hiz = tex->tex.hiz_stride_in_pixels[level];1007} else {1008enum pipe_format format = util_format_linear(surf->base.format);10091010surf->pitch =1011stride |1012r300_translate_colorformat(format) |1013R300_COLOR_TILE(tex->tex.macrotile[level]) |1014R300_COLOR_MICROTILE(tex->tex.microtile) |1015R300_COLOR_ENDIAN(r300_get_endian_swap(format));1016surf->format = r300_translate_out_fmt(format);1017surf->colormask_swizzle =1018r300_translate_colormask_swizzle(format);1019surf->pitch_cmask = tex->tex.cmask_stride_in_pixels;1020}1021}10221023bool r300_resource_get_handle(struct pipe_screen* screen,1024struct pipe_context *ctx,1025struct pipe_resource *texture,1026struct winsys_handle *whandle,1027unsigned usage)1028{1029struct radeon_winsys *rws = r300_screen(screen)->rws;1030struct r300_resource* tex = (struct r300_resource*)texture;10311032if (!tex) {1033return false;1034}10351036whandle->stride = tex->tex.stride_in_bytes[0];1037whandle->offset = 0;10381039return rws->buffer_get_handle(rws, tex->buf, whandle);1040}10411042/* The common texture constructor. */1043static struct r300_resource*1044r300_texture_create_object(struct r300_screen *rscreen,1045const struct pipe_resource *base,1046enum radeon_bo_layout microtile,1047enum radeon_bo_layout macrotile,1048unsigned stride_in_bytes_override,1049struct pb_buffer *buffer)1050{1051struct radeon_winsys *rws = rscreen->rws;1052struct r300_resource *tex = NULL;1053struct radeon_bo_metadata tiling = {};10541055tex = CALLOC_STRUCT(r300_resource);1056if (!tex) {1057goto fail;1058}10591060pipe_reference_init(&tex->b.reference, 1);1061tex->b.screen = &rscreen->screen;1062tex->b.usage = base->usage;1063tex->b.bind = base->bind;1064tex->b.flags = base->flags;1065tex->tex.microtile = microtile;1066tex->tex.macrotile[0] = macrotile;1067tex->tex.stride_in_bytes_override = stride_in_bytes_override;1068tex->domain = (base->flags & R300_RESOURCE_FLAG_TRANSFER ||1069base->usage == PIPE_USAGE_STAGING) ? RADEON_DOMAIN_GTT :1070base->nr_samples > 1 ? RADEON_DOMAIN_VRAM :1071RADEON_DOMAIN_VRAM | RADEON_DOMAIN_GTT;1072tex->buf = buffer;10731074r300_texture_desc_init(rscreen, tex, base);10751076/* Figure out the ideal placement for the texture.. */1077if (tex->domain & RADEON_DOMAIN_VRAM &&1078tex->tex.size_in_bytes >= rscreen->info.vram_size) {1079tex->domain &= ~RADEON_DOMAIN_VRAM;1080tex->domain |= RADEON_DOMAIN_GTT;1081}1082if (tex->domain & RADEON_DOMAIN_GTT &&1083tex->tex.size_in_bytes >= rscreen->info.gart_size) {1084tex->domain &= ~RADEON_DOMAIN_GTT;1085}1086/* Just fail if the texture is too large. */1087if (!tex->domain) {1088goto fail;1089}10901091/* Create the backing buffer if needed. */1092if (!tex->buf) {1093/* Only use the first domain for allocation. Multiple domains are not allowed. */1094unsigned alloc_domain =1095tex->domain & RADEON_DOMAIN_VRAM ? RADEON_DOMAIN_VRAM :1096RADEON_DOMAIN_GTT;10971098tex->buf = rws->buffer_create(rws, tex->tex.size_in_bytes, 2048,1099alloc_domain,1100RADEON_FLAG_NO_SUBALLOC |1101/* Use the reusable pool: */1102RADEON_FLAG_NO_INTERPROCESS_SHARING);11031104if (!tex->buf) {1105goto fail;1106}1107}11081109if (SCREEN_DBG_ON(rscreen, DBG_MSAA) && base->nr_samples > 1) {1110fprintf(stderr, "r300: %ix MSAA %s buffer created\n",1111base->nr_samples,1112util_format_is_depth_or_stencil(base->format) ? "depth" : "color");1113}11141115tiling.u.legacy.microtile = tex->tex.microtile;1116tiling.u.legacy.macrotile = tex->tex.macrotile[0];1117tiling.u.legacy.stride = tex->tex.stride_in_bytes[0];1118rws->buffer_set_metadata(rws, tex->buf, &tiling, NULL);11191120return tex;11211122fail:1123FREE(tex);1124if (buffer)1125pb_reference(&buffer, NULL);1126return NULL;1127}11281129/* Create a new texture. */1130struct pipe_resource *r300_texture_create(struct pipe_screen *screen,1131const struct pipe_resource *base)1132{1133struct r300_screen *rscreen = r300_screen(screen);1134enum radeon_bo_layout microtile, macrotile;11351136if ((base->flags & R300_RESOURCE_FLAG_TRANSFER) ||1137(base->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_LINEAR))) {1138microtile = RADEON_LAYOUT_LINEAR;1139macrotile = RADEON_LAYOUT_LINEAR;1140} else {1141/* This will make the texture_create_function select the layout. */1142microtile = RADEON_LAYOUT_UNKNOWN;1143macrotile = RADEON_LAYOUT_UNKNOWN;1144}11451146return (struct pipe_resource*)1147r300_texture_create_object(rscreen, base, microtile, macrotile,11480, NULL);1149}11501151struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen,1152const struct pipe_resource *base,1153struct winsys_handle *whandle,1154unsigned usage)1155{1156struct r300_screen *rscreen = r300_screen(screen);1157struct radeon_winsys *rws = rscreen->rws;1158struct pb_buffer *buffer;1159struct radeon_bo_metadata tiling = {};11601161/* Support only 2D textures without mipmaps */1162if ((base->target != PIPE_TEXTURE_2D &&1163base->target != PIPE_TEXTURE_RECT) ||1164base->depth0 != 1 ||1165base->last_level != 0) {1166return NULL;1167}11681169buffer = rws->buffer_from_handle(rws, whandle, 0);1170if (!buffer)1171return NULL;11721173rws->buffer_get_metadata(rws, buffer, &tiling, NULL);11741175/* Enforce a microtiled zbuffer. */1176if (util_format_is_depth_or_stencil(base->format) &&1177tiling.u.legacy.microtile == RADEON_LAYOUT_LINEAR) {1178switch (util_format_get_blocksize(base->format)) {1179case 4:1180tiling.u.legacy.microtile = RADEON_LAYOUT_TILED;1181break;11821183case 2:1184tiling.u.legacy.microtile = RADEON_LAYOUT_SQUARETILED;1185break;1186}1187}11881189return (struct pipe_resource*)1190r300_texture_create_object(rscreen, base, tiling.u.legacy.microtile, tiling.u.legacy.macrotile,1191whandle->stride, buffer);1192}11931194struct pipe_surface* r300_create_surface_custom(struct pipe_context * ctx,1195struct pipe_resource* texture,1196const struct pipe_surface *surf_tmpl,1197unsigned width0_override,1198unsigned height0_override)1199{1200struct r300_resource* tex = r300_resource(texture);1201struct r300_surface* surface = CALLOC_STRUCT(r300_surface);1202unsigned level = surf_tmpl->u.tex.level;12031204assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);12051206if (surface) {1207uint32_t offset, tile_height;12081209pipe_reference_init(&surface->base.reference, 1);1210pipe_resource_reference(&surface->base.texture, texture);1211surface->base.context = ctx;1212surface->base.format = surf_tmpl->format;1213surface->base.width = u_minify(width0_override, level);1214surface->base.height = u_minify(height0_override, level);1215surface->base.u.tex.level = level;1216surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;1217surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;12181219surface->buf = tex->buf;12201221/* Prefer VRAM if there are multiple domains to choose from. */1222surface->domain = tex->domain;1223if (surface->domain & RADEON_DOMAIN_VRAM)1224surface->domain &= ~RADEON_DOMAIN_GTT;12251226surface->offset = r300_texture_get_offset(tex, level,1227surf_tmpl->u.tex.first_layer);1228r300_texture_setup_fb_state(surface);12291230/* Parameters for the CBZB clear. */1231surface->cbzb_allowed = tex->tex.cbzb_allowed[level];1232surface->cbzb_width = align(surface->base.width, 64);12331234/* Height must be aligned to the size of a tile. */1235tile_height = r300_get_pixel_alignment(surface->base.format,1236tex->b.nr_samples,1237tex->tex.microtile,1238tex->tex.macrotile[level],1239DIM_HEIGHT, 0);12401241surface->cbzb_height = align((surface->base.height + 1) / 2,1242tile_height);12431244/* Offset must be aligned to 2K and must point at the beginning1245* of a scanline. */1246offset = surface->offset +1247tex->tex.stride_in_bytes[level] * surface->cbzb_height;1248surface->cbzb_midpoint_offset = offset & ~2047;12491250surface->cbzb_pitch = surface->pitch & 0x1ffffc;12511252if (util_format_get_blocksizebits(surface->base.format) == 32)1253surface->cbzb_format = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;1254else1255surface->cbzb_format = R300_DEPTHFORMAT_16BIT_INT_Z;12561257DBG(r300_context(ctx), DBG_CBZB,1258"CBZB Allowed: %s, Dim: %ix%i, Misalignment: %i, Micro: %s, Macro: %s\n",1259surface->cbzb_allowed ? "YES" : " NO",1260surface->cbzb_width, surface->cbzb_height,1261offset & 2047,1262tex->tex.microtile ? "YES" : " NO",1263tex->tex.macrotile[level] ? "YES" : " NO");1264}12651266return &surface->base;1267}12681269struct pipe_surface* r300_create_surface(struct pipe_context * ctx,1270struct pipe_resource* texture,1271const struct pipe_surface *surf_tmpl)1272{1273return r300_create_surface_custom(ctx, texture, surf_tmpl,1274texture->width0,1275texture->height0);1276}12771278void r300_surface_destroy(struct pipe_context *ctx, struct pipe_surface* s)1279{1280pipe_resource_reference(&s->texture, NULL);1281FREE(s);1282}128312841285