diff options
Diffstat (limited to 'src/gallium/drivers/etnaviv/etnaviv_translate.h')
-rw-r--r-- | src/gallium/drivers/etnaviv/etnaviv_translate.h | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/src/gallium/drivers/etnaviv/etnaviv_translate.h b/src/gallium/drivers/etnaviv/etnaviv_translate.h new file mode 100644 index 00000000000..d0623db1472 --- /dev/null +++ b/src/gallium/drivers/etnaviv/etnaviv_translate.h @@ -0,0 +1,516 @@ +/* + * Copyright (c) 2012-2013 Etnaviv Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +/* inlined translation functions between gallium and vivante */ +#ifndef H_TRANSLATE +#define H_TRANSLATE + +#include "pipe/p_defines.h" +#include "pipe/p_format.h" +#include "pipe/p_state.h" + +#include "etnaviv_debug.h" +#include "etnaviv_format.h" +#include "etnaviv_tiling.h" +#include "etnaviv_util.h" +#include "hw/cmdstream.xml.h" +#include "hw/state.xml.h" +#include "hw/state_3d.xml.h" + +#include "util/u_format.h" + +#include <stdio.h> + +/* Returned when there is no match of pipe value to etna value */ +#define ETNA_NO_MATCH (~0) + +static inline uint32_t +translate_cull_face(unsigned cull_face, unsigned front_ccw) +{ + switch (cull_face) { + case PIPE_FACE_NONE: + return VIVS_PA_CONFIG_CULL_FACE_MODE_OFF; + case PIPE_FACE_BACK: + return front_ccw ? VIVS_PA_CONFIG_CULL_FACE_MODE_CW + : VIVS_PA_CONFIG_CULL_FACE_MODE_CCW; + case PIPE_FACE_FRONT: + return front_ccw ? VIVS_PA_CONFIG_CULL_FACE_MODE_CCW + : VIVS_PA_CONFIG_CULL_FACE_MODE_CW; + default: + DBG("Unhandled cull face mode %i", cull_face); + return ETNA_NO_MATCH; + } +} + +static inline uint32_t +translate_polygon_mode(unsigned polygon_mode) +{ + switch (polygon_mode) { + case PIPE_POLYGON_MODE_FILL: + return VIVS_PA_CONFIG_FILL_MODE_SOLID; + case PIPE_POLYGON_MODE_LINE: + return VIVS_PA_CONFIG_FILL_MODE_WIREFRAME; + case PIPE_POLYGON_MODE_POINT: + return VIVS_PA_CONFIG_FILL_MODE_POINT; + default: + DBG("Unhandled polygon mode %i", polygon_mode); + return ETNA_NO_MATCH; + } +} + +static inline uint32_t +translate_stencil_mode(bool enable_0, bool enable_1) +{ + if (enable_0) { + return enable_1 ? VIVS_PE_STENCIL_CONFIG_MODE_TWO_SIDED + : VIVS_PE_STENCIL_CONFIG_MODE_ONE_SIDED; + } else { + return VIVS_PE_STENCIL_CONFIG_MODE_DISABLED; + } +} + +static inline uint32_t +translate_stencil_op(unsigned stencil_op) +{ + switch (stencil_op) { + case PIPE_STENCIL_OP_KEEP: + return STENCIL_OP_KEEP; + case PIPE_STENCIL_OP_ZERO: + return STENCIL_OP_ZERO; + case PIPE_STENCIL_OP_REPLACE: + return STENCIL_OP_REPLACE; + case PIPE_STENCIL_OP_INCR: + return STENCIL_OP_INCR; + case PIPE_STENCIL_OP_DECR: + return STENCIL_OP_DECR; + case PIPE_STENCIL_OP_INCR_WRAP: + return STENCIL_OP_INCR_WRAP; + case PIPE_STENCIL_OP_DECR_WRAP: + return STENCIL_OP_DECR_WRAP; + case PIPE_STENCIL_OP_INVERT: + return STENCIL_OP_INVERT; + default: + DBG("Unhandled stencil op: %i", stencil_op); + return ETNA_NO_MATCH; + } +} + +static inline uint32_t +translate_blend(unsigned blend) +{ + switch (blend) { + case PIPE_BLEND_ADD: + return BLEND_EQ_ADD; + case PIPE_BLEND_SUBTRACT: + return BLEND_EQ_SUBTRACT; + case PIPE_BLEND_REVERSE_SUBTRACT: + return BLEND_EQ_REVERSE_SUBTRACT; + case PIPE_BLEND_MIN: + return BLEND_EQ_MIN; + case PIPE_BLEND_MAX: + return BLEND_EQ_MAX; + default: + DBG("Unhandled blend: %i", blend); + return ETNA_NO_MATCH; + } +} + +static inline uint32_t +translate_blend_factor(unsigned blend_factor) +{ + switch (blend_factor) { + case PIPE_BLENDFACTOR_ONE: + return BLEND_FUNC_ONE; + case PIPE_BLENDFACTOR_SRC_COLOR: + return BLEND_FUNC_SRC_COLOR; + case PIPE_BLENDFACTOR_SRC_ALPHA: + return BLEND_FUNC_SRC_ALPHA; + case PIPE_BLENDFACTOR_DST_ALPHA: + return BLEND_FUNC_DST_ALPHA; + case PIPE_BLENDFACTOR_DST_COLOR: + return BLEND_FUNC_DST_COLOR; + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: + return BLEND_FUNC_SRC_ALPHA_SATURATE; + case PIPE_BLENDFACTOR_CONST_COLOR: + return BLEND_FUNC_CONSTANT_COLOR; + case PIPE_BLENDFACTOR_CONST_ALPHA: + return BLEND_FUNC_CONSTANT_ALPHA; + case PIPE_BLENDFACTOR_ZERO: + return BLEND_FUNC_ZERO; + case PIPE_BLENDFACTOR_INV_SRC_COLOR: + return BLEND_FUNC_ONE_MINUS_SRC_COLOR; + case PIPE_BLENDFACTOR_INV_SRC_ALPHA: + return BLEND_FUNC_ONE_MINUS_SRC_ALPHA; + case PIPE_BLENDFACTOR_INV_DST_ALPHA: + return BLEND_FUNC_ONE_MINUS_DST_ALPHA; + case PIPE_BLENDFACTOR_INV_DST_COLOR: + return BLEND_FUNC_ONE_MINUS_DST_COLOR; + case PIPE_BLENDFACTOR_INV_CONST_COLOR: + return BLEND_FUNC_ONE_MINUS_CONSTANT_COLOR; + case PIPE_BLENDFACTOR_INV_CONST_ALPHA: + return BLEND_FUNC_ONE_MINUS_CONSTANT_ALPHA; + case PIPE_BLENDFACTOR_SRC1_COLOR: + case PIPE_BLENDFACTOR_SRC1_ALPHA: + case PIPE_BLENDFACTOR_INV_SRC1_COLOR: + case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: + default: + DBG("Unhandled blend factor: %i", blend_factor); + return ETNA_NO_MATCH; + } +} + +static inline uint32_t +translate_texture_wrapmode(unsigned wrap) +{ + switch (wrap) { + case PIPE_TEX_WRAP_REPEAT: + return TEXTURE_WRAPMODE_REPEAT; + case PIPE_TEX_WRAP_CLAMP: + return TEXTURE_WRAPMODE_CLAMP_TO_EDGE; + case PIPE_TEX_WRAP_CLAMP_TO_EDGE: + return TEXTURE_WRAPMODE_CLAMP_TO_EDGE; + case PIPE_TEX_WRAP_CLAMP_TO_BORDER: + return TEXTURE_WRAPMODE_CLAMP_TO_EDGE; /* XXX */ + case PIPE_TEX_WRAP_MIRROR_REPEAT: + return TEXTURE_WRAPMODE_MIRRORED_REPEAT; + case PIPE_TEX_WRAP_MIRROR_CLAMP: + return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */ + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: + return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */ + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: + return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */ + default: + DBG("Unhandled texture wrapmode: %i", wrap); + return ETNA_NO_MATCH; + } +} + +static inline uint32_t +translate_texture_mipfilter(unsigned filter) +{ + switch (filter) { + case PIPE_TEX_MIPFILTER_NEAREST: + return TEXTURE_FILTER_NEAREST; + case PIPE_TEX_MIPFILTER_LINEAR: + return TEXTURE_FILTER_LINEAR; + case PIPE_TEX_MIPFILTER_NONE: + return TEXTURE_FILTER_NONE; + default: + DBG("Unhandled texture mipfilter: %i", filter); + return ETNA_NO_MATCH; + } +} + +static inline uint32_t +translate_texture_filter(unsigned filter) +{ + switch (filter) { + case PIPE_TEX_FILTER_NEAREST: + return TEXTURE_FILTER_NEAREST; + case PIPE_TEX_FILTER_LINEAR: + return TEXTURE_FILTER_LINEAR; + /* What about anisotropic? */ + default: + DBG("Unhandled texture filter: %i", filter); + return ETNA_NO_MATCH; + } +} + +/* return a RS "compatible" format for use when copying */ +static inline enum pipe_format +etna_compatible_rs_format(enum pipe_format fmt) +{ + /* YUYV and UYVY are blocksize 4, but 2 bytes per pixel */ + if (fmt == PIPE_FORMAT_YUYV || fmt == PIPE_FORMAT_UYVY) + return PIPE_FORMAT_B4G4R4A4_UNORM; + + switch (util_format_get_blocksize(fmt)) { + case 2: + return PIPE_FORMAT_B4G4R4A4_UNORM; + case 4: + return PIPE_FORMAT_B8G8R8A8_UNORM; + default: + return fmt; + } +} + +static inline int +translate_rb_src_dst_swap(enum pipe_format src, enum pipe_format dst) +{ + return translate_rs_format_rb_swap(src) ^ translate_rs_format_rb_swap(dst); +} + +static inline uint32_t +translate_depth_format(enum pipe_format fmt) +{ + /* Note: Pipe format convention is LSB to MSB, VIVS is MSB to LSB */ + switch (fmt) { + case PIPE_FORMAT_Z16_UNORM: + return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16; + case PIPE_FORMAT_X8Z24_UNORM: + return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D24S8; + case PIPE_FORMAT_S8_UINT_Z24_UNORM: + return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D24S8; + default: + return ETNA_NO_MATCH; + } +} + +/* render target format for MSAA */ +static inline uint32_t +translate_msaa_format(enum pipe_format fmt) +{ + /* Note: Pipe format convention is LSB to MSB, VIVS is MSB to LSB */ + switch (fmt) { + case PIPE_FORMAT_B4G4R4X4_UNORM: + return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A4R4G4B4; + case PIPE_FORMAT_B4G4R4A4_UNORM: + return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A4R4G4B4; + case PIPE_FORMAT_B5G5R5X1_UNORM: + return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A1R5G5B5; + case PIPE_FORMAT_B5G5R5A1_UNORM: + return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A1R5G5B5; + case PIPE_FORMAT_B5G6R5_UNORM: + return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_R5G6B5; + case PIPE_FORMAT_B8G8R8X8_UNORM: + return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_X8R8G8B8; + case PIPE_FORMAT_B8G8R8A8_UNORM: + return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A8R8G8B8; + /* MSAA with YUYV not supported */ + default: + return ETNA_NO_MATCH; + } +} + +/* Return normalization flag for vertex element format */ +static inline uint32_t +translate_vertex_format_normalize(enum pipe_format fmt) +{ + const struct util_format_description *desc = util_format_description(fmt); + if (!desc) + return VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF; + + /* assumes that normalization of channel 0 holds for all channels; + * this holds for all vertex formats that we support */ + return desc->channel[0].normalized + ? VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_ON + : VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF; +} + +static inline uint32_t +translate_index_size(unsigned index_size) +{ + switch (index_size) { + case 1: + return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_CHAR; + case 2: + return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_SHORT; + case 4: + return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_INT; + default: + DBG("Unhandled index size %i", index_size); + return ETNA_NO_MATCH; + } +} + +static inline uint32_t +translate_draw_mode(unsigned mode) +{ + switch (mode) { + case PIPE_PRIM_POINTS: + return PRIMITIVE_TYPE_POINTS; + case PIPE_PRIM_LINES: + return PRIMITIVE_TYPE_LINES; + case PIPE_PRIM_LINE_LOOP: + return PRIMITIVE_TYPE_LINE_LOOP; + case PIPE_PRIM_LINE_STRIP: + return PRIMITIVE_TYPE_LINE_STRIP; + case PIPE_PRIM_TRIANGLES: + return PRIMITIVE_TYPE_TRIANGLES; + case PIPE_PRIM_TRIANGLE_STRIP: + return PRIMITIVE_TYPE_TRIANGLE_STRIP; + case PIPE_PRIM_TRIANGLE_FAN: + return PRIMITIVE_TYPE_TRIANGLE_FAN; + case PIPE_PRIM_QUADS: + return PRIMITIVE_TYPE_QUADS; + default: + DBG("Unhandled draw mode primitive %i", mode); + return ETNA_NO_MATCH; + } +} + +/* Get size multiple for size of texture/rendertarget with a certain layout + * This is affected by many different parameters: + * - A horizontal multiple of 16 is used when possible as resolve can be used + * at the cost of only a little bit extra memory usage. + * - If the surface is to be used with the resolve engine, set rs_align true. + * If set, a horizontal multiple of 16 will be used for tiled and linear, + * otherwise one of 16. However, such a surface will be incompatible + * with the samplers if the GPU does hot support the HALIGN feature. + * - If the surface is supertiled, horizontal and vertical multiple is always 64 + * - If the surface is multi tiled or supertiled, make sure that the vertical size + * is a multiple of the number of pixel pipes as well. + * */ +static inline void +etna_layout_multiple(unsigned layout, unsigned pixel_pipes, bool rs_align, + unsigned *paddingX, unsigned *paddingY, unsigned *halign) +{ + switch (layout) { + case ETNA_LAYOUT_LINEAR: + *paddingX = rs_align ? 16 : 4; + *paddingY = 1; + *halign = rs_align ? TEXTURE_HALIGN_SIXTEEN : TEXTURE_HALIGN_FOUR; + break; + case ETNA_LAYOUT_TILED: + *paddingX = rs_align ? 16 : 4; + *paddingY = 4; + *halign = rs_align ? TEXTURE_HALIGN_SIXTEEN : TEXTURE_HALIGN_FOUR; + break; + case ETNA_LAYOUT_SUPER_TILED: + *paddingX = 64; + *paddingY = 64; + *halign = TEXTURE_HALIGN_SUPER_TILED; + break; + case ETNA_LAYOUT_MULTI_TILED: + *paddingX = 16; + *paddingY = 4 * pixel_pipes; + *halign = TEXTURE_HALIGN_SPLIT_TILED; + break; + case ETNA_LAYOUT_MULTI_SUPERTILED: + *paddingX = 64; + *paddingY = 64 * pixel_pipes; + *halign = TEXTURE_HALIGN_SPLIT_SUPER_TILED; + break; + default: + DBG("Unhandled layout %i", layout); + } +} + +/* return 32-bit clear pattern for color */ +static inline uint32_t +translate_clear_color(enum pipe_format format, + const union pipe_color_union *color) +{ + uint32_t clear_value = 0; + + // XXX util_pack_color + switch (format) { + case PIPE_FORMAT_B8G8R8A8_UNORM: + case PIPE_FORMAT_B8G8R8X8_UNORM: + clear_value = etna_cfloat_to_uintN(color->f[2], 8) | + (etna_cfloat_to_uintN(color->f[1], 8) << 8) | + (etna_cfloat_to_uintN(color->f[0], 8) << 16) | + (etna_cfloat_to_uintN(color->f[3], 8) << 24); + break; + case PIPE_FORMAT_B4G4R4X4_UNORM: + case PIPE_FORMAT_B4G4R4A4_UNORM: + clear_value = etna_cfloat_to_uintN(color->f[2], 4) | + (etna_cfloat_to_uintN(color->f[1], 4) << 4) | + (etna_cfloat_to_uintN(color->f[0], 4) << 8) | + (etna_cfloat_to_uintN(color->f[3], 4) << 12); + clear_value |= clear_value << 16; + break; + case PIPE_FORMAT_B5G5R5X1_UNORM: + case PIPE_FORMAT_B5G5R5A1_UNORM: + clear_value = etna_cfloat_to_uintN(color->f[2], 5) | + (etna_cfloat_to_uintN(color->f[1], 5) << 5) | + (etna_cfloat_to_uintN(color->f[0], 5) << 10) | + (etna_cfloat_to_uintN(color->f[3], 1) << 15); + clear_value |= clear_value << 16; + break; + case PIPE_FORMAT_B5G6R5_UNORM: + clear_value = etna_cfloat_to_uintN(color->f[2], 5) | + (etna_cfloat_to_uintN(color->f[1], 6) << 5) | + (etna_cfloat_to_uintN(color->f[0], 5) << 11); + clear_value |= clear_value << 16; + break; + default: + DBG("Unhandled pipe format for color clear: %i", format); + } + + return clear_value; +} + +static inline uint32_t +translate_clear_depth_stencil(enum pipe_format format, float depth, + unsigned stencil) +{ + uint32_t clear_value = 0; + + // XXX util_pack_color + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + clear_value = etna_cfloat_to_uintN(depth, 16); + clear_value |= clear_value << 16; + break; + case PIPE_FORMAT_X8Z24_UNORM: + case PIPE_FORMAT_S8_UINT_Z24_UNORM: + clear_value = (etna_cfloat_to_uintN(depth, 24) << 8) | (stencil & 0xFF); + break; + default: + DBG("Unhandled pipe format for depth stencil clear: %i", format); + } + return clear_value; +} + +/* Convert MSAA number of samples to x and y scaling factor and + * VIVS_GL_MULTI_SAMPLE_CONFIG value. + * Return true if supported and false otherwise. */ +static inline bool +translate_samples_to_xyscale(int num_samples, int *xscale_out, int *yscale_out, + uint32_t *config_out) +{ + int xscale, yscale; + uint32_t config; + + switch (num_samples) { + case 0: + case 1: + xscale = 1; + yscale = 1; + config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE; + break; + case 2: + xscale = 2; + yscale = 1; + config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X; + break; + case 4: + xscale = 2; + yscale = 2; + config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X; + break; + default: + return false; + } + + if (xscale_out) + *xscale_out = xscale; + if (yscale_out) + *yscale_out = yscale; + if (config_out) + *config_out = config; + + return true; +} + +#endif |