101e04c3fSmrg/****************************************************************************
201e04c3fSmrg * Copyright (C) 2015 Intel Corporation.   All Rights Reserved.
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg ***************************************************************************/
2301e04c3fSmrg
2401e04c3fSmrg#include "swr_context.h"
2501e04c3fSmrg#include "swr_public.h"
2601e04c3fSmrg#include "swr_screen.h"
2701e04c3fSmrg#include "swr_resource.h"
2801e04c3fSmrg#include "swr_fence.h"
2901e04c3fSmrg#include "gen_knobs.h"
3001e04c3fSmrg
3101e04c3fSmrg#include "pipe/p_screen.h"
3201e04c3fSmrg#include "pipe/p_defines.h"
3301e04c3fSmrg#include "util/u_memory.h"
347ec681f3Smrg#include "util/format/u_format.h"
3501e04c3fSmrg#include "util/u_inlines.h"
3601e04c3fSmrg#include "util/u_cpu_detect.h"
377ec681f3Smrg#include "util/format/u_format_s3tc.h"
3801e04c3fSmrg#include "util/u_string.h"
399f464c52Smaya#include "util/u_screen.h"
4001e04c3fSmrg
417ec681f3Smrg#include "frontend/sw_winsys.h"
4201e04c3fSmrg
4301e04c3fSmrg#include "jit_api.h"
4401e04c3fSmrg
4501e04c3fSmrg#include "memory/TilingFunctions.h"
4601e04c3fSmrg
4701e04c3fSmrg#include <stdio.h>
4801e04c3fSmrg#include <map>
4901e04c3fSmrg
5001e04c3fSmrg/*
5101e04c3fSmrg * Max texture sizes
5201e04c3fSmrg * XXX Check max texture size values against core and sampler.
5301e04c3fSmrg */
5401e04c3fSmrg#define SWR_MAX_TEXTURE_SIZE (2 * 1024 * 1024 * 1024ULL) /* 2GB */
557ec681f3Smrg/* Not all texture formats can fit into 2GB limit, but we have to
567ec681f3Smrg   live with that. See lp_limits.h for more details */
577ec681f3Smrg#define SWR_MAX_TEXTURE_2D_SIZE 16384
5801e04c3fSmrg#define SWR_MAX_TEXTURE_3D_LEVELS 12  /* 2K x 2K x 2K for now */
5901e04c3fSmrg#define SWR_MAX_TEXTURE_CUBE_LEVELS 14  /* 8K x 8K for now */
6001e04c3fSmrg#define SWR_MAX_TEXTURE_ARRAY_LAYERS 512 /* 8K x 512 / 8K x 8K x 512 */
6101e04c3fSmrg
6201e04c3fSmrg/* Default max client_copy_limit */
6301e04c3fSmrg#define SWR_CLIENT_COPY_LIMIT 8192
6401e04c3fSmrg
6501e04c3fSmrg/* Flag indicates creation of alternate surface, to prevent recursive loop
6601e04c3fSmrg * in resource creation when msaa_force_enable is set. */
6701e04c3fSmrg#define SWR_RESOURCE_FLAG_ALT_SURFACE (PIPE_RESOURCE_FLAG_DRV_PRIV << 0)
6801e04c3fSmrg
6901e04c3fSmrg
7001e04c3fSmrgstatic const char *
7101e04c3fSmrgswr_get_name(struct pipe_screen *screen)
7201e04c3fSmrg{
7301e04c3fSmrg   static char buf[100];
747ec681f3Smrg   snprintf(buf, sizeof(buf), "SWR (LLVM " MESA_LLVM_VERSION_STRING ", %u bits)",
757ec681f3Smrg            lp_native_vector_width);
7601e04c3fSmrg   return buf;
7701e04c3fSmrg}
7801e04c3fSmrg
7901e04c3fSmrgstatic const char *
8001e04c3fSmrgswr_get_vendor(struct pipe_screen *screen)
8101e04c3fSmrg{
8201e04c3fSmrg   return "Intel Corporation";
8301e04c3fSmrg}
8401e04c3fSmrg
857ec681f3Smrgstatic bool
8601e04c3fSmrgswr_is_format_supported(struct pipe_screen *_screen,
8701e04c3fSmrg                        enum pipe_format format,
8801e04c3fSmrg                        enum pipe_texture_target target,
8901e04c3fSmrg                        unsigned sample_count,
9001e04c3fSmrg                        unsigned storage_sample_count,
9101e04c3fSmrg                        unsigned bind)
9201e04c3fSmrg{
9301e04c3fSmrg   struct swr_screen *screen = swr_screen(_screen);
9401e04c3fSmrg   struct sw_winsys *winsys = screen->winsys;
9501e04c3fSmrg   const struct util_format_description *format_desc;
9601e04c3fSmrg
9701e04c3fSmrg   assert(target == PIPE_BUFFER || target == PIPE_TEXTURE_1D
9801e04c3fSmrg          || target == PIPE_TEXTURE_1D_ARRAY
9901e04c3fSmrg          || target == PIPE_TEXTURE_2D
10001e04c3fSmrg          || target == PIPE_TEXTURE_2D_ARRAY
10101e04c3fSmrg          || target == PIPE_TEXTURE_RECT
10201e04c3fSmrg          || target == PIPE_TEXTURE_3D
10301e04c3fSmrg          || target == PIPE_TEXTURE_CUBE
10401e04c3fSmrg          || target == PIPE_TEXTURE_CUBE_ARRAY);
10501e04c3fSmrg
10601e04c3fSmrg   if (MAX2(1, sample_count) != MAX2(1, storage_sample_count))
10701e04c3fSmrg      return false;
10801e04c3fSmrg
10901e04c3fSmrg   format_desc = util_format_description(format);
11001e04c3fSmrg   if (!format_desc)
1117ec681f3Smrg      return false;
11201e04c3fSmrg
11301e04c3fSmrg   if ((sample_count > screen->msaa_max_count)
11401e04c3fSmrg      || !util_is_power_of_two_or_zero(sample_count))
1157ec681f3Smrg      return false;
11601e04c3fSmrg
11701e04c3fSmrg   if (bind & PIPE_BIND_DISPLAY_TARGET) {
11801e04c3fSmrg      if (!winsys->is_displaytarget_format_supported(winsys, bind, format))
1197ec681f3Smrg         return false;
12001e04c3fSmrg   }
12101e04c3fSmrg
12201e04c3fSmrg   if (bind & PIPE_BIND_RENDER_TARGET) {
12301e04c3fSmrg      if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
1247ec681f3Smrg         return false;
12501e04c3fSmrg
12601e04c3fSmrg      if (mesa_to_swr_format(format) == (SWR_FORMAT)-1)
1277ec681f3Smrg         return false;
12801e04c3fSmrg
12901e04c3fSmrg      /*
13001e04c3fSmrg       * Although possible, it is unnatural to render into compressed or YUV
13101e04c3fSmrg       * surfaces. So disable these here to avoid going into weird paths
1327ec681f3Smrg       * inside gallium frontends.
13301e04c3fSmrg       */
13401e04c3fSmrg      if (format_desc->block.width != 1 || format_desc->block.height != 1)
1357ec681f3Smrg         return false;
13601e04c3fSmrg   }
13701e04c3fSmrg
13801e04c3fSmrg   if (bind & PIPE_BIND_DEPTH_STENCIL) {
13901e04c3fSmrg      if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
1407ec681f3Smrg         return false;
14101e04c3fSmrg
14201e04c3fSmrg      if (mesa_to_swr_format(format) == (SWR_FORMAT)-1)
1437ec681f3Smrg         return false;
14401e04c3fSmrg   }
14501e04c3fSmrg
1467ec681f3Smrg   if (bind & PIPE_BIND_VERTEX_BUFFER) {
1477ec681f3Smrg      if (mesa_to_swr_format(format) == (SWR_FORMAT)-1) {
1487ec681f3Smrg         return false;
1497ec681f3Smrg      }
1507ec681f3Smrg   }
1517ec681f3Smrg
1527ec681f3Smrg   if (format_desc->layout == UTIL_FORMAT_LAYOUT_ASTC ||
1537ec681f3Smrg       format_desc->layout == UTIL_FORMAT_LAYOUT_FXT1)
1547ec681f3Smrg   {
1557ec681f3Smrg      return false;
15601e04c3fSmrg   }
15701e04c3fSmrg
15801e04c3fSmrg   if (format_desc->layout == UTIL_FORMAT_LAYOUT_ETC &&
15901e04c3fSmrg       format != PIPE_FORMAT_ETC1_RGB8) {
1607ec681f3Smrg      return false;
1617ec681f3Smrg   }
1627ec681f3Smrg
1637ec681f3Smrg   if ((bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW)) &&
1647ec681f3Smrg       ((bind & PIPE_BIND_DISPLAY_TARGET) == 0)) {
1657ec681f3Smrg      /* Disable all 3-channel formats, where channel size != 32 bits.
1667ec681f3Smrg       * In some cases we run into crashes (in generate_unswizzled_blend()),
1677ec681f3Smrg       * for 3-channel RGB16 variants, there was an apparent LLVM bug.
1687ec681f3Smrg       * In any case, disabling the shallower 3-channel formats avoids a
1697ec681f3Smrg       * number of issues with GL_ARB_copy_image support.
1707ec681f3Smrg       */
1717ec681f3Smrg      if (format_desc->is_array &&
1727ec681f3Smrg          format_desc->nr_channels == 3 &&
1737ec681f3Smrg          format_desc->block.bits != 96) {
1747ec681f3Smrg         return false;
1757ec681f3Smrg      }
17601e04c3fSmrg   }
17701e04c3fSmrg
17801e04c3fSmrg   return TRUE;
17901e04c3fSmrg}
18001e04c3fSmrg
18101e04c3fSmrgstatic int
18201e04c3fSmrgswr_get_param(struct pipe_screen *screen, enum pipe_cap param)
18301e04c3fSmrg{
18401e04c3fSmrg   switch (param) {
18501e04c3fSmrg      /* limits */
18601e04c3fSmrg   case PIPE_CAP_MAX_RENDER_TARGETS:
18701e04c3fSmrg      return PIPE_MAX_COLOR_BUFS;
1887ec681f3Smrg   case PIPE_CAP_MAX_TEXTURE_2D_SIZE:
1897ec681f3Smrg      return SWR_MAX_TEXTURE_2D_SIZE;
19001e04c3fSmrg   case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
19101e04c3fSmrg      return SWR_MAX_TEXTURE_3D_LEVELS;
19201e04c3fSmrg   case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
19301e04c3fSmrg      return SWR_MAX_TEXTURE_CUBE_LEVELS;
19401e04c3fSmrg   case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
19501e04c3fSmrg      return MAX_SO_STREAMS;
19601e04c3fSmrg   case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
19701e04c3fSmrg   case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
19801e04c3fSmrg      return MAX_ATTRIBUTES * 4;
19901e04c3fSmrg   case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
20001e04c3fSmrg   case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
20101e04c3fSmrg      return 1024;
20201e04c3fSmrg   case PIPE_CAP_MAX_VERTEX_STREAMS:
2037ec681f3Smrg      return 4;
20401e04c3fSmrg   case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
20501e04c3fSmrg      return 2048;
20601e04c3fSmrg   case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
20701e04c3fSmrg      return SWR_MAX_TEXTURE_ARRAY_LAYERS;
2087ec681f3Smrg   case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET:
20901e04c3fSmrg   case PIPE_CAP_MIN_TEXEL_OFFSET:
21001e04c3fSmrg      return -8;
2117ec681f3Smrg   case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET:
21201e04c3fSmrg   case PIPE_CAP_MAX_TEXEL_OFFSET:
21301e04c3fSmrg      return 7;
2147ec681f3Smrg   case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
2157ec681f3Smrg      return 4;
21601e04c3fSmrg   case PIPE_CAP_GLSL_FEATURE_LEVEL:
21701e04c3fSmrg      return 330;
21801e04c3fSmrg   case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
21901e04c3fSmrg      return 140;
22001e04c3fSmrg   case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
22101e04c3fSmrg      return 16;
22201e04c3fSmrg   case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
22301e04c3fSmrg      return 64;
22401e04c3fSmrg   case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
22501e04c3fSmrg      return 65536;
22601e04c3fSmrg   case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
22701e04c3fSmrg      return 1;
2287ec681f3Smrg   case PIPE_CAP_MAX_VIEWPORTS:
2297ec681f3Smrg      return KNOB_NUM_VIEWPORTS_SCISSORS;
23001e04c3fSmrg   case PIPE_CAP_ENDIANNESS:
23101e04c3fSmrg      return PIPE_ENDIAN_NATIVE;
23201e04c3fSmrg
23301e04c3fSmrg      /* supported features */
23401e04c3fSmrg   case PIPE_CAP_NPOT_TEXTURES:
23501e04c3fSmrg   case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
23601e04c3fSmrg   case PIPE_CAP_MIXED_COLOR_DEPTH_BITS:
2377ec681f3Smrg   case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:
2387ec681f3Smrg   case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:
2397ec681f3Smrg   case PIPE_CAP_VERTEX_SHADER_SATURATE:
24001e04c3fSmrg   case PIPE_CAP_POINT_SPRITE:
24101e04c3fSmrg   case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
24201e04c3fSmrg   case PIPE_CAP_OCCLUSION_QUERY:
24301e04c3fSmrg   case PIPE_CAP_QUERY_TIME_ELAPSED:
24401e04c3fSmrg   case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
24501e04c3fSmrg   case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
24601e04c3fSmrg   case PIPE_CAP_TEXTURE_MIRROR_CLAMP_TO_EDGE:
24701e04c3fSmrg   case PIPE_CAP_TEXTURE_SWIZZLE:
24801e04c3fSmrg   case PIPE_CAP_BLEND_EQUATION_SEPARATE:
24901e04c3fSmrg   case PIPE_CAP_INDEP_BLEND_ENABLE:
25001e04c3fSmrg   case PIPE_CAP_INDEP_BLEND_FUNC:
25101e04c3fSmrg   case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
25201e04c3fSmrg   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
25301e04c3fSmrg   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
25401e04c3fSmrg   case PIPE_CAP_DEPTH_CLIP_DISABLE:
25501e04c3fSmrg   case PIPE_CAP_PRIMITIVE_RESTART:
2567ec681f3Smrg   case PIPE_CAP_PRIMITIVE_RESTART_FIXED_INDEX:
25701e04c3fSmrg   case PIPE_CAP_TGSI_INSTANCEID:
25801e04c3fSmrg   case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
25901e04c3fSmrg   case PIPE_CAP_START_INSTANCE:
26001e04c3fSmrg   case PIPE_CAP_SEAMLESS_CUBE_MAP:
26101e04c3fSmrg   case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
26201e04c3fSmrg   case PIPE_CAP_CONDITIONAL_RENDER:
26301e04c3fSmrg   case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
26401e04c3fSmrg   case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
26501e04c3fSmrg   case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
26601e04c3fSmrg   case PIPE_CAP_USER_VERTEX_BUFFERS:
26701e04c3fSmrg   case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
26801e04c3fSmrg   case PIPE_CAP_QUERY_TIMESTAMP:
26901e04c3fSmrg   case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
27001e04c3fSmrg   case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:
27101e04c3fSmrg   case PIPE_CAP_DRAW_INDIRECT:
27201e04c3fSmrg   case PIPE_CAP_UMA:
27301e04c3fSmrg   case PIPE_CAP_CONDITIONAL_RENDER_INVERTED:
27401e04c3fSmrg   case PIPE_CAP_CLIP_HALFZ:
27501e04c3fSmrg   case PIPE_CAP_POLYGON_OFFSET_CLAMP:
27601e04c3fSmrg   case PIPE_CAP_DEPTH_BOUNDS_TEST:
27701e04c3fSmrg   case PIPE_CAP_CLEAR_TEXTURE:
27801e04c3fSmrg   case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
27901e04c3fSmrg   case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
28001e04c3fSmrg   case PIPE_CAP_CULL_DISTANCE:
28101e04c3fSmrg   case PIPE_CAP_CUBE_MAP_ARRAY:
28201e04c3fSmrg   case PIPE_CAP_DOUBLES:
2837ec681f3Smrg   case PIPE_CAP_TEXTURE_QUERY_LOD:
2847ec681f3Smrg   case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:
2857ec681f3Smrg   case PIPE_CAP_TGSI_TG4_COMPONENT_IN_SWIZZLE:
2867ec681f3Smrg   case PIPE_CAP_QUERY_SO_OVERFLOW:
2877ec681f3Smrg   case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
28801e04c3fSmrg      return 1;
28901e04c3fSmrg
2907ec681f3Smrg   case PIPE_CAP_SHAREABLE_SHADERS:
2917ec681f3Smrg      return 0;
2927ec681f3Smrg
29301e04c3fSmrg   /* MSAA support
29401e04c3fSmrg    * If user has explicitly set max_sample_count = 1 (via SWR_MSAA_MAX_COUNT)
29501e04c3fSmrg    * then disable all MSAA support and go back to old (FAKE_SW_MSAA) caps. */
29601e04c3fSmrg   case PIPE_CAP_TEXTURE_MULTISAMPLE:
29701e04c3fSmrg   case PIPE_CAP_MULTISAMPLE_Z_RESOLVE:
29801e04c3fSmrg      return (swr_screen(screen)->msaa_max_count > 1) ? 1 : 0;
29901e04c3fSmrg   case PIPE_CAP_FAKE_SW_MSAA:
30001e04c3fSmrg      return (swr_screen(screen)->msaa_max_count > 1) ? 0 : 1;
30101e04c3fSmrg
30201e04c3fSmrg   /* fetch jit change for 2-4GB buffers requires alignment */
30301e04c3fSmrg   case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
30401e04c3fSmrg   case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
30501e04c3fSmrg   case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
30601e04c3fSmrg      return 1;
30701e04c3fSmrg
30801e04c3fSmrg      /* unsupported features */
30901e04c3fSmrg   case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
31001e04c3fSmrg   case PIPE_CAP_PCI_GROUP:
31101e04c3fSmrg   case PIPE_CAP_PCI_BUS:
31201e04c3fSmrg   case PIPE_CAP_PCI_DEVICE:
31301e04c3fSmrg   case PIPE_CAP_PCI_FUNCTION:
31401e04c3fSmrg   case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
31501e04c3fSmrg      return 0;
31601e04c3fSmrg   case PIPE_CAP_MAX_GS_INVOCATIONS:
31701e04c3fSmrg      return 32;
31801e04c3fSmrg   case PIPE_CAP_MAX_SHADER_BUFFER_SIZE:
31901e04c3fSmrg      return 1 << 27;
3209f464c52Smaya   case PIPE_CAP_MAX_VARYINGS:
3219f464c52Smaya      return 32;
32201e04c3fSmrg
32301e04c3fSmrg   case PIPE_CAP_VENDOR_ID:
32401e04c3fSmrg      return 0xFFFFFFFF;
32501e04c3fSmrg   case PIPE_CAP_DEVICE_ID:
32601e04c3fSmrg      return 0xFFFFFFFF;
32701e04c3fSmrg   case PIPE_CAP_ACCELERATED:
32801e04c3fSmrg      return 0;
32901e04c3fSmrg   case PIPE_CAP_VIDEO_MEMORY: {
33001e04c3fSmrg      /* XXX: Do we want to return the full amount of system memory ? */
33101e04c3fSmrg      uint64_t system_memory;
33201e04c3fSmrg
33301e04c3fSmrg      if (!os_get_total_physical_memory(&system_memory))
33401e04c3fSmrg         return 0;
33501e04c3fSmrg
33601e04c3fSmrg      return (int)(system_memory >> 20);
33701e04c3fSmrg   }
3389f464c52Smaya   default:
3399f464c52Smaya      return u_pipe_screen_get_param_defaults(screen, param);
34001e04c3fSmrg   }
34101e04c3fSmrg}
34201e04c3fSmrg
34301e04c3fSmrgstatic int
34401e04c3fSmrgswr_get_shader_param(struct pipe_screen *screen,
34501e04c3fSmrg                     enum pipe_shader_type shader,
34601e04c3fSmrg                     enum pipe_shader_cap param)
34701e04c3fSmrg{
3487ec681f3Smrg   if (shader != PIPE_SHADER_VERTEX &&
3497ec681f3Smrg       shader != PIPE_SHADER_FRAGMENT &&
3507ec681f3Smrg       shader != PIPE_SHADER_GEOMETRY &&
3517ec681f3Smrg       shader != PIPE_SHADER_TESS_CTRL &&
3527ec681f3Smrg       shader != PIPE_SHADER_TESS_EVAL)
3537ec681f3Smrg      return 0;
35401e04c3fSmrg
3557ec681f3Smrg   if (param == PIPE_SHADER_CAP_MAX_SHADER_BUFFERS ||
3567ec681f3Smrg       param == PIPE_SHADER_CAP_MAX_SHADER_IMAGES) {
3577ec681f3Smrg      return 0;
3587ec681f3Smrg   }
3597ec681f3Smrg
3607ec681f3Smrg   return gallivm_get_shader_param(param);
36101e04c3fSmrg}
36201e04c3fSmrg
36301e04c3fSmrg
36401e04c3fSmrgstatic float
36501e04c3fSmrgswr_get_paramf(struct pipe_screen *screen, enum pipe_capf param)
36601e04c3fSmrg{
36701e04c3fSmrg   switch (param) {
36801e04c3fSmrg   case PIPE_CAPF_MAX_LINE_WIDTH:
36901e04c3fSmrg   case PIPE_CAPF_MAX_LINE_WIDTH_AA:
37001e04c3fSmrg   case PIPE_CAPF_MAX_POINT_WIDTH:
37101e04c3fSmrg      return 255.0; /* arbitrary */
37201e04c3fSmrg   case PIPE_CAPF_MAX_POINT_WIDTH_AA:
37301e04c3fSmrg      return 0.0;
37401e04c3fSmrg   case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
37501e04c3fSmrg      return 0.0;
37601e04c3fSmrg   case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
37701e04c3fSmrg      return 16.0; /* arbitrary */
37801e04c3fSmrg   case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
37901e04c3fSmrg   case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
38001e04c3fSmrg   case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
38101e04c3fSmrg      return 0.0f;
38201e04c3fSmrg   }
38301e04c3fSmrg   /* should only get here on unhandled cases */
38401e04c3fSmrg   debug_printf("Unexpected PIPE_CAPF %d query\n", param);
38501e04c3fSmrg   return 0.0;
38601e04c3fSmrg}
38701e04c3fSmrg
38801e04c3fSmrgSWR_FORMAT
38901e04c3fSmrgmesa_to_swr_format(enum pipe_format format)
39001e04c3fSmrg{
39101e04c3fSmrg   static const std::map<pipe_format,SWR_FORMAT> mesa2swr = {
39201e04c3fSmrg      /* depth / stencil */
39301e04c3fSmrg      {PIPE_FORMAT_Z16_UNORM,              R16_UNORM}, // z
39401e04c3fSmrg      {PIPE_FORMAT_Z32_FLOAT,              R32_FLOAT}, // z
39501e04c3fSmrg      {PIPE_FORMAT_Z24_UNORM_S8_UINT,      R24_UNORM_X8_TYPELESS}, // z
39601e04c3fSmrg      {PIPE_FORMAT_Z24X8_UNORM,            R24_UNORM_X8_TYPELESS}, // z
39701e04c3fSmrg      {PIPE_FORMAT_Z32_FLOAT_S8X24_UINT,   R32_FLOAT_X8X24_TYPELESS}, // z
39801e04c3fSmrg
39901e04c3fSmrg      /* alpha */
40001e04c3fSmrg      {PIPE_FORMAT_A8_UNORM,               A8_UNORM},
40101e04c3fSmrg      {PIPE_FORMAT_A16_UNORM,              A16_UNORM},
40201e04c3fSmrg      {PIPE_FORMAT_A16_FLOAT,              A16_FLOAT},
40301e04c3fSmrg      {PIPE_FORMAT_A32_FLOAT,              A32_FLOAT},
40401e04c3fSmrg
40501e04c3fSmrg      /* odd sizes, bgr */
40601e04c3fSmrg      {PIPE_FORMAT_B5G6R5_UNORM,           B5G6R5_UNORM},
40701e04c3fSmrg      {PIPE_FORMAT_B5G6R5_SRGB,            B5G6R5_UNORM_SRGB},
40801e04c3fSmrg      {PIPE_FORMAT_B5G5R5A1_UNORM,         B5G5R5A1_UNORM},
40901e04c3fSmrg      {PIPE_FORMAT_B5G5R5X1_UNORM,         B5G5R5X1_UNORM},
41001e04c3fSmrg      {PIPE_FORMAT_B4G4R4A4_UNORM,         B4G4R4A4_UNORM},
41101e04c3fSmrg      {PIPE_FORMAT_B8G8R8A8_UNORM,         B8G8R8A8_UNORM},
41201e04c3fSmrg      {PIPE_FORMAT_B8G8R8A8_SRGB,          B8G8R8A8_UNORM_SRGB},
41301e04c3fSmrg      {PIPE_FORMAT_B8G8R8X8_UNORM,         B8G8R8X8_UNORM},
41401e04c3fSmrg      {PIPE_FORMAT_B8G8R8X8_SRGB,          B8G8R8X8_UNORM_SRGB},
41501e04c3fSmrg
41601e04c3fSmrg      /* rgb10a2 */
41701e04c3fSmrg      {PIPE_FORMAT_R10G10B10A2_UNORM,      R10G10B10A2_UNORM},
41801e04c3fSmrg      {PIPE_FORMAT_R10G10B10A2_SNORM,      R10G10B10A2_SNORM},
41901e04c3fSmrg      {PIPE_FORMAT_R10G10B10A2_USCALED,    R10G10B10A2_USCALED},
42001e04c3fSmrg      {PIPE_FORMAT_R10G10B10A2_SSCALED,    R10G10B10A2_SSCALED},
42101e04c3fSmrg      {PIPE_FORMAT_R10G10B10A2_UINT,       R10G10B10A2_UINT},
42201e04c3fSmrg
42301e04c3fSmrg      /* rgb10x2 */
42401e04c3fSmrg      {PIPE_FORMAT_R10G10B10X2_USCALED,    R10G10B10X2_USCALED},
42501e04c3fSmrg
42601e04c3fSmrg      /* bgr10a2 */
42701e04c3fSmrg      {PIPE_FORMAT_B10G10R10A2_UNORM,      B10G10R10A2_UNORM},
42801e04c3fSmrg      {PIPE_FORMAT_B10G10R10A2_SNORM,      B10G10R10A2_SNORM},
42901e04c3fSmrg      {PIPE_FORMAT_B10G10R10A2_USCALED,    B10G10R10A2_USCALED},
43001e04c3fSmrg      {PIPE_FORMAT_B10G10R10A2_SSCALED,    B10G10R10A2_SSCALED},
43101e04c3fSmrg      {PIPE_FORMAT_B10G10R10A2_UINT,       B10G10R10A2_UINT},
43201e04c3fSmrg
43301e04c3fSmrg      /* bgr10x2 */
43401e04c3fSmrg      {PIPE_FORMAT_B10G10R10X2_UNORM,      B10G10R10X2_UNORM},
43501e04c3fSmrg
43601e04c3fSmrg      /* r11g11b10 */
43701e04c3fSmrg      {PIPE_FORMAT_R11G11B10_FLOAT,        R11G11B10_FLOAT},
43801e04c3fSmrg
43901e04c3fSmrg      /* 32 bits per component */
44001e04c3fSmrg      {PIPE_FORMAT_R32_FLOAT,              R32_FLOAT},
44101e04c3fSmrg      {PIPE_FORMAT_R32G32_FLOAT,           R32G32_FLOAT},
44201e04c3fSmrg      {PIPE_FORMAT_R32G32B32_FLOAT,        R32G32B32_FLOAT},
44301e04c3fSmrg      {PIPE_FORMAT_R32G32B32A32_FLOAT,     R32G32B32A32_FLOAT},
44401e04c3fSmrg      {PIPE_FORMAT_R32G32B32X32_FLOAT,     R32G32B32X32_FLOAT},
44501e04c3fSmrg
44601e04c3fSmrg      {PIPE_FORMAT_R32_USCALED,            R32_USCALED},
44701e04c3fSmrg      {PIPE_FORMAT_R32G32_USCALED,         R32G32_USCALED},
44801e04c3fSmrg      {PIPE_FORMAT_R32G32B32_USCALED,      R32G32B32_USCALED},
44901e04c3fSmrg      {PIPE_FORMAT_R32G32B32A32_USCALED,   R32G32B32A32_USCALED},
45001e04c3fSmrg
45101e04c3fSmrg      {PIPE_FORMAT_R32_SSCALED,            R32_SSCALED},
45201e04c3fSmrg      {PIPE_FORMAT_R32G32_SSCALED,         R32G32_SSCALED},
45301e04c3fSmrg      {PIPE_FORMAT_R32G32B32_SSCALED,      R32G32B32_SSCALED},
45401e04c3fSmrg      {PIPE_FORMAT_R32G32B32A32_SSCALED,   R32G32B32A32_SSCALED},
45501e04c3fSmrg
45601e04c3fSmrg      {PIPE_FORMAT_R32_UINT,               R32_UINT},
45701e04c3fSmrg      {PIPE_FORMAT_R32G32_UINT,            R32G32_UINT},
45801e04c3fSmrg      {PIPE_FORMAT_R32G32B32_UINT,         R32G32B32_UINT},
45901e04c3fSmrg      {PIPE_FORMAT_R32G32B32A32_UINT,      R32G32B32A32_UINT},
46001e04c3fSmrg
46101e04c3fSmrg      {PIPE_FORMAT_R32_SINT,               R32_SINT},
46201e04c3fSmrg      {PIPE_FORMAT_R32G32_SINT,            R32G32_SINT},
46301e04c3fSmrg      {PIPE_FORMAT_R32G32B32_SINT,         R32G32B32_SINT},
46401e04c3fSmrg      {PIPE_FORMAT_R32G32B32A32_SINT,      R32G32B32A32_SINT},
46501e04c3fSmrg
46601e04c3fSmrg      /* 16 bits per component */
46701e04c3fSmrg      {PIPE_FORMAT_R16_UNORM,              R16_UNORM},
46801e04c3fSmrg      {PIPE_FORMAT_R16G16_UNORM,           R16G16_UNORM},
46901e04c3fSmrg      {PIPE_FORMAT_R16G16B16_UNORM,        R16G16B16_UNORM},
47001e04c3fSmrg      {PIPE_FORMAT_R16G16B16A16_UNORM,     R16G16B16A16_UNORM},
47101e04c3fSmrg      {PIPE_FORMAT_R16G16B16X16_UNORM,     R16G16B16X16_UNORM},
47201e04c3fSmrg
47301e04c3fSmrg      {PIPE_FORMAT_R16_USCALED,            R16_USCALED},
47401e04c3fSmrg      {PIPE_FORMAT_R16G16_USCALED,         R16G16_USCALED},
47501e04c3fSmrg      {PIPE_FORMAT_R16G16B16_USCALED,      R16G16B16_USCALED},
47601e04c3fSmrg      {PIPE_FORMAT_R16G16B16A16_USCALED,   R16G16B16A16_USCALED},
47701e04c3fSmrg
47801e04c3fSmrg      {PIPE_FORMAT_R16_SNORM,              R16_SNORM},
47901e04c3fSmrg      {PIPE_FORMAT_R16G16_SNORM,           R16G16_SNORM},
48001e04c3fSmrg      {PIPE_FORMAT_R16G16B16_SNORM,        R16G16B16_SNORM},
48101e04c3fSmrg      {PIPE_FORMAT_R16G16B16A16_SNORM,     R16G16B16A16_SNORM},
48201e04c3fSmrg
48301e04c3fSmrg      {PIPE_FORMAT_R16_SSCALED,            R16_SSCALED},
48401e04c3fSmrg      {PIPE_FORMAT_R16G16_SSCALED,         R16G16_SSCALED},
48501e04c3fSmrg      {PIPE_FORMAT_R16G16B16_SSCALED,      R16G16B16_SSCALED},
48601e04c3fSmrg      {PIPE_FORMAT_R16G16B16A16_SSCALED,   R16G16B16A16_SSCALED},
48701e04c3fSmrg
48801e04c3fSmrg      {PIPE_FORMAT_R16_UINT,               R16_UINT},
48901e04c3fSmrg      {PIPE_FORMAT_R16G16_UINT,            R16G16_UINT},
49001e04c3fSmrg      {PIPE_FORMAT_R16G16B16_UINT,         R16G16B16_UINT},
49101e04c3fSmrg      {PIPE_FORMAT_R16G16B16A16_UINT,      R16G16B16A16_UINT},
49201e04c3fSmrg
49301e04c3fSmrg      {PIPE_FORMAT_R16_SINT,               R16_SINT},
49401e04c3fSmrg      {PIPE_FORMAT_R16G16_SINT,            R16G16_SINT},
49501e04c3fSmrg      {PIPE_FORMAT_R16G16B16_SINT,         R16G16B16_SINT},
49601e04c3fSmrg      {PIPE_FORMAT_R16G16B16A16_SINT,      R16G16B16A16_SINT},
49701e04c3fSmrg
49801e04c3fSmrg      {PIPE_FORMAT_R16_FLOAT,              R16_FLOAT},
49901e04c3fSmrg      {PIPE_FORMAT_R16G16_FLOAT,           R16G16_FLOAT},
50001e04c3fSmrg      {PIPE_FORMAT_R16G16B16_FLOAT,        R16G16B16_FLOAT},
50101e04c3fSmrg      {PIPE_FORMAT_R16G16B16A16_FLOAT,     R16G16B16A16_FLOAT},
50201e04c3fSmrg      {PIPE_FORMAT_R16G16B16X16_FLOAT,     R16G16B16X16_FLOAT},
50301e04c3fSmrg
50401e04c3fSmrg      /* 8 bits per component */
50501e04c3fSmrg      {PIPE_FORMAT_R8_UNORM,               R8_UNORM},
50601e04c3fSmrg      {PIPE_FORMAT_R8G8_UNORM,             R8G8_UNORM},
50701e04c3fSmrg      {PIPE_FORMAT_R8G8B8_UNORM,           R8G8B8_UNORM},
50801e04c3fSmrg      {PIPE_FORMAT_R8G8B8_SRGB,            R8G8B8_UNORM_SRGB},
50901e04c3fSmrg      {PIPE_FORMAT_R8G8B8A8_UNORM,         R8G8B8A8_UNORM},
51001e04c3fSmrg      {PIPE_FORMAT_R8G8B8A8_SRGB,          R8G8B8A8_UNORM_SRGB},
51101e04c3fSmrg      {PIPE_FORMAT_R8G8B8X8_UNORM,         R8G8B8X8_UNORM},
51201e04c3fSmrg      {PIPE_FORMAT_R8G8B8X8_SRGB,          R8G8B8X8_UNORM_SRGB},
51301e04c3fSmrg
51401e04c3fSmrg      {PIPE_FORMAT_R8_USCALED,             R8_USCALED},
51501e04c3fSmrg      {PIPE_FORMAT_R8G8_USCALED,           R8G8_USCALED},
51601e04c3fSmrg      {PIPE_FORMAT_R8G8B8_USCALED,         R8G8B8_USCALED},
51701e04c3fSmrg      {PIPE_FORMAT_R8G8B8A8_USCALED,       R8G8B8A8_USCALED},
51801e04c3fSmrg
51901e04c3fSmrg      {PIPE_FORMAT_R8_SNORM,               R8_SNORM},
52001e04c3fSmrg      {PIPE_FORMAT_R8G8_SNORM,             R8G8_SNORM},
52101e04c3fSmrg      {PIPE_FORMAT_R8G8B8_SNORM,           R8G8B8_SNORM},
52201e04c3fSmrg      {PIPE_FORMAT_R8G8B8A8_SNORM,         R8G8B8A8_SNORM},
52301e04c3fSmrg
52401e04c3fSmrg      {PIPE_FORMAT_R8_SSCALED,             R8_SSCALED},
52501e04c3fSmrg      {PIPE_FORMAT_R8G8_SSCALED,           R8G8_SSCALED},
52601e04c3fSmrg      {PIPE_FORMAT_R8G8B8_SSCALED,         R8G8B8_SSCALED},
52701e04c3fSmrg      {PIPE_FORMAT_R8G8B8A8_SSCALED,       R8G8B8A8_SSCALED},
52801e04c3fSmrg
52901e04c3fSmrg      {PIPE_FORMAT_R8_UINT,                R8_UINT},
53001e04c3fSmrg      {PIPE_FORMAT_R8G8_UINT,              R8G8_UINT},
53101e04c3fSmrg      {PIPE_FORMAT_R8G8B8_UINT,            R8G8B8_UINT},
53201e04c3fSmrg      {PIPE_FORMAT_R8G8B8A8_UINT,          R8G8B8A8_UINT},
53301e04c3fSmrg
53401e04c3fSmrg      {PIPE_FORMAT_R8_SINT,                R8_SINT},
53501e04c3fSmrg      {PIPE_FORMAT_R8G8_SINT,              R8G8_SINT},
53601e04c3fSmrg      {PIPE_FORMAT_R8G8B8_SINT,            R8G8B8_SINT},
53701e04c3fSmrg      {PIPE_FORMAT_R8G8B8A8_SINT,          R8G8B8A8_SINT},
53801e04c3fSmrg
53901e04c3fSmrg      /* These formats are valid for vertex data, but should not be used
54001e04c3fSmrg       * for render targets.
54101e04c3fSmrg       */
54201e04c3fSmrg
54301e04c3fSmrg      {PIPE_FORMAT_R32_FIXED,              R32_SFIXED},
54401e04c3fSmrg      {PIPE_FORMAT_R32G32_FIXED,           R32G32_SFIXED},
54501e04c3fSmrg      {PIPE_FORMAT_R32G32B32_FIXED,        R32G32B32_SFIXED},
54601e04c3fSmrg      {PIPE_FORMAT_R32G32B32A32_FIXED,     R32G32B32A32_SFIXED},
54701e04c3fSmrg
54801e04c3fSmrg      {PIPE_FORMAT_R64_FLOAT,              R64_FLOAT},
54901e04c3fSmrg      {PIPE_FORMAT_R64G64_FLOAT,           R64G64_FLOAT},
55001e04c3fSmrg      {PIPE_FORMAT_R64G64B64_FLOAT,        R64G64B64_FLOAT},
55101e04c3fSmrg      {PIPE_FORMAT_R64G64B64A64_FLOAT,     R64G64B64A64_FLOAT},
55201e04c3fSmrg
55301e04c3fSmrg      /* These formats have entries in SWR but don't have Load/StoreTile
55401e04c3fSmrg       * implementations. That means these aren't renderable, and thus having
55501e04c3fSmrg       * a mapping entry here is detrimental.
55601e04c3fSmrg       */
55701e04c3fSmrg      /*
55801e04c3fSmrg
55901e04c3fSmrg      {PIPE_FORMAT_L8_UNORM,               L8_UNORM},
56001e04c3fSmrg      {PIPE_FORMAT_I8_UNORM,               I8_UNORM},
56101e04c3fSmrg      {PIPE_FORMAT_L8A8_UNORM,             L8A8_UNORM},
56201e04c3fSmrg      {PIPE_FORMAT_L16_UNORM,              L16_UNORM},
56301e04c3fSmrg      {PIPE_FORMAT_UYVY,                   YCRCB_SWAPUVY},
56401e04c3fSmrg
56501e04c3fSmrg      {PIPE_FORMAT_L8_SRGB,                L8_UNORM_SRGB},
56601e04c3fSmrg      {PIPE_FORMAT_L8A8_SRGB,              L8A8_UNORM_SRGB},
56701e04c3fSmrg
56801e04c3fSmrg      {PIPE_FORMAT_DXT1_RGBA,              BC1_UNORM},
56901e04c3fSmrg      {PIPE_FORMAT_DXT3_RGBA,              BC2_UNORM},
57001e04c3fSmrg      {PIPE_FORMAT_DXT5_RGBA,              BC3_UNORM},
57101e04c3fSmrg
57201e04c3fSmrg      {PIPE_FORMAT_DXT1_SRGBA,             BC1_UNORM_SRGB},
57301e04c3fSmrg      {PIPE_FORMAT_DXT3_SRGBA,             BC2_UNORM_SRGB},
57401e04c3fSmrg      {PIPE_FORMAT_DXT5_SRGBA,             BC3_UNORM_SRGB},
57501e04c3fSmrg
57601e04c3fSmrg      {PIPE_FORMAT_RGTC1_UNORM,            BC4_UNORM},
57701e04c3fSmrg      {PIPE_FORMAT_RGTC1_SNORM,            BC4_SNORM},
57801e04c3fSmrg      {PIPE_FORMAT_RGTC2_UNORM,            BC5_UNORM},
57901e04c3fSmrg      {PIPE_FORMAT_RGTC2_SNORM,            BC5_SNORM},
58001e04c3fSmrg
58101e04c3fSmrg      {PIPE_FORMAT_L16A16_UNORM,           L16A16_UNORM},
58201e04c3fSmrg      {PIPE_FORMAT_I16_UNORM,              I16_UNORM},
58301e04c3fSmrg      {PIPE_FORMAT_L16_FLOAT,              L16_FLOAT},
58401e04c3fSmrg      {PIPE_FORMAT_L16A16_FLOAT,           L16A16_FLOAT},
58501e04c3fSmrg      {PIPE_FORMAT_I16_FLOAT,              I16_FLOAT},
58601e04c3fSmrg      {PIPE_FORMAT_L32_FLOAT,              L32_FLOAT},
58701e04c3fSmrg      {PIPE_FORMAT_L32A32_FLOAT,           L32A32_FLOAT},
58801e04c3fSmrg      {PIPE_FORMAT_I32_FLOAT,              I32_FLOAT},
58901e04c3fSmrg
59001e04c3fSmrg      {PIPE_FORMAT_I8_UINT,                I8_UINT},
59101e04c3fSmrg      {PIPE_FORMAT_L8_UINT,                L8_UINT},
59201e04c3fSmrg      {PIPE_FORMAT_L8A8_UINT,              L8A8_UINT},
59301e04c3fSmrg
59401e04c3fSmrg      {PIPE_FORMAT_I8_SINT,                I8_SINT},
59501e04c3fSmrg      {PIPE_FORMAT_L8_SINT,                L8_SINT},
59601e04c3fSmrg      {PIPE_FORMAT_L8A8_SINT,              L8A8_SINT},
59701e04c3fSmrg
59801e04c3fSmrg      */
59901e04c3fSmrg   };
60001e04c3fSmrg
60101e04c3fSmrg   auto it = mesa2swr.find(format);
60201e04c3fSmrg   if (it == mesa2swr.end())
60301e04c3fSmrg      return (SWR_FORMAT)-1;
60401e04c3fSmrg   else
60501e04c3fSmrg      return it->second;
60601e04c3fSmrg}
60701e04c3fSmrg
6087ec681f3Smrgstatic bool
60901e04c3fSmrgswr_displaytarget_layout(struct swr_screen *screen, struct swr_resource *res)
61001e04c3fSmrg{
61101e04c3fSmrg   struct sw_winsys *winsys = screen->winsys;
61201e04c3fSmrg   struct sw_displaytarget *dt;
61301e04c3fSmrg
61401e04c3fSmrg   const unsigned width = align(res->swr.width, res->swr.halign);
61501e04c3fSmrg   const unsigned height = align(res->swr.height, res->swr.valign);
61601e04c3fSmrg
61701e04c3fSmrg   UINT stride;
61801e04c3fSmrg   dt = winsys->displaytarget_create(winsys,
61901e04c3fSmrg                                     res->base.bind,
62001e04c3fSmrg                                     res->base.format,
62101e04c3fSmrg                                     width, height,
62201e04c3fSmrg                                     64, NULL,
62301e04c3fSmrg                                     &stride);
62401e04c3fSmrg
62501e04c3fSmrg   if (dt == NULL)
6267ec681f3Smrg      return false;
62701e04c3fSmrg
62801e04c3fSmrg   void *map = winsys->displaytarget_map(winsys, dt, 0);
62901e04c3fSmrg
63001e04c3fSmrg   res->display_target = dt;
63101e04c3fSmrg   res->swr.xpBaseAddress = (gfxptr_t)map;
63201e04c3fSmrg
63301e04c3fSmrg   /* Clear the display target surface */
63401e04c3fSmrg   if (map)
63501e04c3fSmrg      memset(map, 0, height * stride);
63601e04c3fSmrg
63701e04c3fSmrg   winsys->displaytarget_unmap(winsys, dt);
63801e04c3fSmrg
6397ec681f3Smrg   return true;
64001e04c3fSmrg}
64101e04c3fSmrg
64201e04c3fSmrgstatic bool
64301e04c3fSmrgswr_texture_layout(struct swr_screen *screen,
64401e04c3fSmrg                   struct swr_resource *res,
6457ec681f3Smrg                   bool allocate)
64601e04c3fSmrg{
64701e04c3fSmrg   struct pipe_resource *pt = &res->base;
64801e04c3fSmrg
64901e04c3fSmrg   pipe_format fmt = pt->format;
65001e04c3fSmrg   const struct util_format_description *desc = util_format_description(fmt);
65101e04c3fSmrg
65201e04c3fSmrg   res->has_depth = util_format_has_depth(desc);
65301e04c3fSmrg   res->has_stencil = util_format_has_stencil(desc);
65401e04c3fSmrg
65501e04c3fSmrg   if (res->has_stencil && !res->has_depth)
65601e04c3fSmrg      fmt = PIPE_FORMAT_R8_UINT;
65701e04c3fSmrg
65801e04c3fSmrg   /* We always use the SWR layout. For 2D and 3D textures this looks like:
65901e04c3fSmrg    *
66001e04c3fSmrg    * |<------- pitch ------->|
66101e04c3fSmrg    * +=======================+-------
66201e04c3fSmrg    * |Array 0                |   ^
66301e04c3fSmrg    * |                       |   |
66401e04c3fSmrg    * |        Level 0        |   |
66501e04c3fSmrg    * |                       |   |
66601e04c3fSmrg    * |                       | qpitch
66701e04c3fSmrg    * +-----------+-----------+   |
66801e04c3fSmrg    * |           | L2L2L2L2  |   |
66901e04c3fSmrg    * |  Level 1  | L3L3      |   |
67001e04c3fSmrg    * |           | L4        |   v
67101e04c3fSmrg    * +===========+===========+-------
67201e04c3fSmrg    * |Array 1                |
67301e04c3fSmrg    * |                       |
67401e04c3fSmrg    * |        Level 0        |
67501e04c3fSmrg    * |                       |
67601e04c3fSmrg    * |                       |
67701e04c3fSmrg    * +-----------+-----------+
67801e04c3fSmrg    * |           | L2L2L2L2  |
67901e04c3fSmrg    * |  Level 1  | L3L3      |
68001e04c3fSmrg    * |           | L4        |
68101e04c3fSmrg    * +===========+===========+
68201e04c3fSmrg    *
68301e04c3fSmrg    * The overall width in bytes is known as the pitch, while the overall
68401e04c3fSmrg    * height in rows is the qpitch. Array slices are laid out logically below
68501e04c3fSmrg    * one another, qpitch rows apart. For 3D surfaces, the "level" values are
68601e04c3fSmrg    * just invalid for the higher array numbers (since depth is also
68701e04c3fSmrg    * minified). 1D and 1D array surfaces are stored effectively the same way,
68801e04c3fSmrg    * except that pitch never plays into it. All the levels are logically
68901e04c3fSmrg    * adjacent to each other on the X axis. The qpitch becomes the number of
69001e04c3fSmrg    * elements between array slices, while the pitch is unused.
69101e04c3fSmrg    *
69201e04c3fSmrg    * Each level's sizes are subject to the valign and halign settings of the
69301e04c3fSmrg    * surface. For compressed formats that swr is unaware of, we will use an
69401e04c3fSmrg    * appropriately-sized uncompressed format, and scale the widths/heights.
69501e04c3fSmrg    *
69601e04c3fSmrg    * This surface is stored inside res->swr. For depth/stencil textures,
69701e04c3fSmrg    * res->secondary will have an identically-laid-out but R8_UINT-formatted
69801e04c3fSmrg    * stencil tree. In the Z32F_S8 case, the primary surface still has 64-bpp
69901e04c3fSmrg    * texels, to simplify map/unmap logic which copies the stencil values
70001e04c3fSmrg    * in/out.
70101e04c3fSmrg    */
70201e04c3fSmrg
70301e04c3fSmrg   res->swr.width = pt->width0;
70401e04c3fSmrg   res->swr.height = pt->height0;
70501e04c3fSmrg   res->swr.type = swr_convert_target_type(pt->target);
70601e04c3fSmrg   res->swr.tileMode = SWR_TILE_NONE;
70701e04c3fSmrg   res->swr.format = mesa_to_swr_format(fmt);
70801e04c3fSmrg   res->swr.numSamples = std::max(1u, pt->nr_samples);
70901e04c3fSmrg
71001e04c3fSmrg   if (pt->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) {
71101e04c3fSmrg      res->swr.halign = KNOB_MACROTILE_X_DIM;
71201e04c3fSmrg      res->swr.valign = KNOB_MACROTILE_Y_DIM;
71301e04c3fSmrg
71401e04c3fSmrg      /* If SWR_MSAA_FORCE_ENABLE is set, turn on MSAA and override requested
71501e04c3fSmrg       * surface sample count. */
71601e04c3fSmrg      if (screen->msaa_force_enable) {
71701e04c3fSmrg         res->swr.numSamples = screen->msaa_max_count;
7187ec681f3Smrg         swr_print_info("swr_texture_layout: forcing sample count: %d\n",
71901e04c3fSmrg                 res->swr.numSamples);
72001e04c3fSmrg      }
72101e04c3fSmrg   } else {
72201e04c3fSmrg      res->swr.halign = 1;
72301e04c3fSmrg      res->swr.valign = 1;
72401e04c3fSmrg   }
72501e04c3fSmrg
72601e04c3fSmrg   unsigned halign = res->swr.halign * util_format_get_blockwidth(fmt);
72701e04c3fSmrg   unsigned width = align(pt->width0, halign);
72801e04c3fSmrg   if (pt->target == PIPE_TEXTURE_1D || pt->target == PIPE_TEXTURE_1D_ARRAY) {
72901e04c3fSmrg      for (int level = 1; level <= pt->last_level; level++)
73001e04c3fSmrg         width += align(u_minify(pt->width0, level), halign);
73101e04c3fSmrg      res->swr.pitch = util_format_get_blocksize(fmt);
73201e04c3fSmrg      res->swr.qpitch = util_format_get_nblocksx(fmt, width);
73301e04c3fSmrg   } else {
73401e04c3fSmrg      // The pitch is the overall width of the texture in bytes. Most of the
73501e04c3fSmrg      // time this is the pitch of level 0 since all the other levels fit
73601e04c3fSmrg      // underneath it. However in some degenerate situations, the width of
73701e04c3fSmrg      // level1 + level2 may be larger. In that case, we use those
73801e04c3fSmrg      // widths. This can happen if, e.g. halign is 32, and the width of level
73901e04c3fSmrg      // 0 is 32 or less. In that case, the aligned levels 1 and 2 will also
74001e04c3fSmrg      // be 32 each, adding up to 64.
74101e04c3fSmrg      unsigned valign = res->swr.valign * util_format_get_blockheight(fmt);
74201e04c3fSmrg      if (pt->last_level > 1) {
74301e04c3fSmrg         width = std::max<uint32_t>(
74401e04c3fSmrg               width,
74501e04c3fSmrg               align(u_minify(pt->width0, 1), halign) +
74601e04c3fSmrg               align(u_minify(pt->width0, 2), halign));
74701e04c3fSmrg      }
74801e04c3fSmrg      res->swr.pitch = util_format_get_stride(fmt, width);
74901e04c3fSmrg
75001e04c3fSmrg      // The qpitch is controlled by either the height of the second LOD, or
75101e04c3fSmrg      // the combination of all the later LODs.
75201e04c3fSmrg      unsigned height = align(pt->height0, valign);
75301e04c3fSmrg      if (pt->last_level == 1) {
75401e04c3fSmrg         height += align(u_minify(pt->height0, 1), valign);
75501e04c3fSmrg      } else if (pt->last_level > 1) {
75601e04c3fSmrg         unsigned level1 = align(u_minify(pt->height0, 1), valign);
75701e04c3fSmrg         unsigned level2 = 0;
75801e04c3fSmrg         for (int level = 2; level <= pt->last_level; level++) {
75901e04c3fSmrg            level2 += align(u_minify(pt->height0, level), valign);
76001e04c3fSmrg         }
76101e04c3fSmrg         height += std::max(level1, level2);
76201e04c3fSmrg      }
76301e04c3fSmrg      res->swr.qpitch = util_format_get_nblocksy(fmt, height);
76401e04c3fSmrg   }
76501e04c3fSmrg
76601e04c3fSmrg   if (pt->target == PIPE_TEXTURE_3D)
76701e04c3fSmrg      res->swr.depth = pt->depth0;
76801e04c3fSmrg   else
76901e04c3fSmrg      res->swr.depth = pt->array_size;
77001e04c3fSmrg
77101e04c3fSmrg   // Fix up swr format if necessary so that LOD offset computation works
77201e04c3fSmrg   if (res->swr.format == (SWR_FORMAT)-1) {
77301e04c3fSmrg      switch (util_format_get_blocksize(fmt)) {
77401e04c3fSmrg      default:
77501e04c3fSmrg         unreachable("Unexpected format block size");
77601e04c3fSmrg      case 1: res->swr.format = R8_UINT; break;
77701e04c3fSmrg      case 2: res->swr.format = R16_UINT; break;
77801e04c3fSmrg      case 4: res->swr.format = R32_UINT; break;
77901e04c3fSmrg      case 8:
78001e04c3fSmrg         if (util_format_is_compressed(fmt))
78101e04c3fSmrg            res->swr.format = BC4_UNORM;
78201e04c3fSmrg         else
78301e04c3fSmrg            res->swr.format = R32G32_UINT;
78401e04c3fSmrg         break;
78501e04c3fSmrg      case 16:
78601e04c3fSmrg         if (util_format_is_compressed(fmt))
78701e04c3fSmrg            res->swr.format = BC5_UNORM;
78801e04c3fSmrg         else
78901e04c3fSmrg            res->swr.format = R32G32B32A32_UINT;
79001e04c3fSmrg         break;
79101e04c3fSmrg      }
79201e04c3fSmrg   }
79301e04c3fSmrg
79401e04c3fSmrg   for (int level = 0; level <= pt->last_level; level++) {
79501e04c3fSmrg      res->mip_offsets[level] =
79601e04c3fSmrg         ComputeSurfaceOffset<false>(0, 0, 0, 0, 0, level, &res->swr);
79701e04c3fSmrg   }
79801e04c3fSmrg
79901e04c3fSmrg   size_t total_size = (uint64_t)res->swr.depth * res->swr.qpitch *
80001e04c3fSmrg                                 res->swr.pitch * res->swr.numSamples;
801993e1d59Smrg
802993e1d59Smrg   // Let non-sampled textures (e.g. buffer objects) bypass the size limit
803993e1d59Smrg   if (swr_resource_is_texture(&res->base) && total_size > SWR_MAX_TEXTURE_SIZE)
80401e04c3fSmrg      return false;
80501e04c3fSmrg
80601e04c3fSmrg   if (allocate) {
80701e04c3fSmrg      res->swr.xpBaseAddress = (gfxptr_t)AlignedMalloc(total_size, 64);
80801e04c3fSmrg      if (!res->swr.xpBaseAddress)
80901e04c3fSmrg         return false;
81001e04c3fSmrg
81101e04c3fSmrg      if (res->has_depth && res->has_stencil) {
81201e04c3fSmrg         res->secondary = res->swr;
81301e04c3fSmrg         res->secondary.format = R8_UINT;
81401e04c3fSmrg         res->secondary.pitch = res->swr.pitch / util_format_get_blocksize(fmt);
81501e04c3fSmrg
81601e04c3fSmrg         for (int level = 0; level <= pt->last_level; level++) {
81701e04c3fSmrg            res->secondary_mip_offsets[level] =
81801e04c3fSmrg               ComputeSurfaceOffset<false>(0, 0, 0, 0, 0, level, &res->secondary);
81901e04c3fSmrg         }
82001e04c3fSmrg
82101e04c3fSmrg         total_size = res->secondary.depth * res->secondary.qpitch *
82201e04c3fSmrg                      res->secondary.pitch * res->secondary.numSamples;
82301e04c3fSmrg
82401e04c3fSmrg         res->secondary.xpBaseAddress = (gfxptr_t) AlignedMalloc(total_size, 64);
82501e04c3fSmrg         if (!res->secondary.xpBaseAddress) {
82601e04c3fSmrg            AlignedFree((void *)res->swr.xpBaseAddress);
82701e04c3fSmrg            return false;
82801e04c3fSmrg         }
82901e04c3fSmrg      }
83001e04c3fSmrg   }
83101e04c3fSmrg
83201e04c3fSmrg   return true;
83301e04c3fSmrg}
83401e04c3fSmrg
8357ec681f3Smrgstatic bool
83601e04c3fSmrgswr_can_create_resource(struct pipe_screen *screen,
83701e04c3fSmrg                        const struct pipe_resource *templat)
83801e04c3fSmrg{
83901e04c3fSmrg   struct swr_resource res;
84001e04c3fSmrg   memset(&res, 0, sizeof(res));
84101e04c3fSmrg   res.base = *templat;
84201e04c3fSmrg   return swr_texture_layout(swr_screen(screen), &res, false);
84301e04c3fSmrg}
84401e04c3fSmrg
84501e04c3fSmrg/* Helper function that conditionally creates a single-sample resolve resource
84601e04c3fSmrg * and attaches it to main multisample resource. */
8477ec681f3Smrgstatic bool
84801e04c3fSmrgswr_create_resolve_resource(struct pipe_screen *_screen,
84901e04c3fSmrg                            struct swr_resource *msaa_res)
85001e04c3fSmrg{
85101e04c3fSmrg   struct swr_screen *screen = swr_screen(_screen);
85201e04c3fSmrg
85301e04c3fSmrg   /* If resource is multisample, create a single-sample resolve resource */
85401e04c3fSmrg   if (msaa_res->base.nr_samples > 1 || (screen->msaa_force_enable &&
85501e04c3fSmrg            !(msaa_res->base.flags & SWR_RESOURCE_FLAG_ALT_SURFACE))) {
85601e04c3fSmrg
85701e04c3fSmrg      /* Create a single-sample copy of the resource.  Copy the original
85801e04c3fSmrg       * resource parameters and set flag to prevent recursion when re-calling
85901e04c3fSmrg       * resource_create */
86001e04c3fSmrg      struct pipe_resource alt_template = msaa_res->base;
86101e04c3fSmrg      alt_template.nr_samples = 0;
86201e04c3fSmrg      alt_template.flags |= SWR_RESOURCE_FLAG_ALT_SURFACE;
86301e04c3fSmrg
86401e04c3fSmrg      /* Note: Display_target is a special single-sample resource, only the
86501e04c3fSmrg       * display_target has been created already. */
86601e04c3fSmrg      if (msaa_res->base.bind & (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT
86701e04c3fSmrg               | PIPE_BIND_SHARED)) {
86801e04c3fSmrg         /* Allocate the multisample buffers. */
86901e04c3fSmrg         if (!swr_texture_layout(screen, msaa_res, true))
87001e04c3fSmrg            return false;
87101e04c3fSmrg
87201e04c3fSmrg         /* Alt resource will only be bound as PIPE_BIND_RENDER_TARGET
87301e04c3fSmrg          * remove the DISPLAY_TARGET, SCANOUT, and SHARED bindings */
87401e04c3fSmrg         alt_template.bind = PIPE_BIND_RENDER_TARGET;
87501e04c3fSmrg      }
87601e04c3fSmrg
87701e04c3fSmrg      /* Allocate single-sample resolve surface */
87801e04c3fSmrg      struct pipe_resource *alt;
87901e04c3fSmrg      alt = _screen->resource_create(_screen, &alt_template);
88001e04c3fSmrg      if (!alt)
88101e04c3fSmrg         return false;
88201e04c3fSmrg
88301e04c3fSmrg      /* Attach it to the multisample resource */
88401e04c3fSmrg      msaa_res->resolve_target = alt;
88501e04c3fSmrg
88601e04c3fSmrg      /* Hang resolve surface state off the multisample surface state to so
88701e04c3fSmrg       * StoreTiles knows where to resolve the surface. */
88801e04c3fSmrg      msaa_res->swr.xpAuxBaseAddress = (gfxptr_t)&swr_resource(alt)->swr;
88901e04c3fSmrg   }
89001e04c3fSmrg
89101e04c3fSmrg   return true; /* success */
89201e04c3fSmrg}
89301e04c3fSmrg
89401e04c3fSmrgstatic struct pipe_resource *
89501e04c3fSmrgswr_resource_create(struct pipe_screen *_screen,
89601e04c3fSmrg                    const struct pipe_resource *templat)
89701e04c3fSmrg{
89801e04c3fSmrg   struct swr_screen *screen = swr_screen(_screen);
89901e04c3fSmrg   struct swr_resource *res = CALLOC_STRUCT(swr_resource);
90001e04c3fSmrg   if (!res)
90101e04c3fSmrg      return NULL;
90201e04c3fSmrg
90301e04c3fSmrg   res->base = *templat;
90401e04c3fSmrg   pipe_reference_init(&res->base.reference, 1);
90501e04c3fSmrg   res->base.screen = &screen->base;
90601e04c3fSmrg
90701e04c3fSmrg   if (swr_resource_is_texture(&res->base)) {
90801e04c3fSmrg      if (res->base.bind & (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT
90901e04c3fSmrg                            | PIPE_BIND_SHARED)) {
91001e04c3fSmrg         /* displayable surface
91101e04c3fSmrg          * first call swr_texture_layout without allocating to finish
91201e04c3fSmrg          * filling out the SWR_SURFACE_STATE in res */
91301e04c3fSmrg         swr_texture_layout(screen, res, false);
91401e04c3fSmrg         if (!swr_displaytarget_layout(screen, res))
91501e04c3fSmrg            goto fail;
91601e04c3fSmrg      } else {
91701e04c3fSmrg         /* texture map */
91801e04c3fSmrg         if (!swr_texture_layout(screen, res, true))
91901e04c3fSmrg            goto fail;
92001e04c3fSmrg      }
92101e04c3fSmrg
92201e04c3fSmrg      /* If resource was multisample, create resolve resource and attach
92301e04c3fSmrg       * it to multisample resource. */
92401e04c3fSmrg      if (!swr_create_resolve_resource(_screen, res))
92501e04c3fSmrg            goto fail;
92601e04c3fSmrg
92701e04c3fSmrg   } else {
92801e04c3fSmrg      /* other data (vertex buffer, const buffer, etc) */
92901e04c3fSmrg      assert(util_format_get_blocksize(templat->format) == 1);
93001e04c3fSmrg      assert(templat->height0 == 1);
93101e04c3fSmrg      assert(templat->depth0 == 1);
93201e04c3fSmrg      assert(templat->last_level == 0);
93301e04c3fSmrg
93401e04c3fSmrg      /* Easiest to just call swr_texture_layout, as it sets up
93501e04c3fSmrg       * SWR_SURFACE_STATE in res */
93601e04c3fSmrg      if (!swr_texture_layout(screen, res, true))
93701e04c3fSmrg         goto fail;
93801e04c3fSmrg   }
93901e04c3fSmrg
94001e04c3fSmrg   return &res->base;
94101e04c3fSmrg
94201e04c3fSmrgfail:
94301e04c3fSmrg   FREE(res);
94401e04c3fSmrg   return NULL;
94501e04c3fSmrg}
94601e04c3fSmrg
94701e04c3fSmrgstatic void
94801e04c3fSmrgswr_resource_destroy(struct pipe_screen *p_screen, struct pipe_resource *pt)
94901e04c3fSmrg{
95001e04c3fSmrg   struct swr_screen *screen = swr_screen(p_screen);
95101e04c3fSmrg   struct swr_resource *spr = swr_resource(pt);
95201e04c3fSmrg
95301e04c3fSmrg   if (spr->display_target) {
95401e04c3fSmrg      /* If resource is display target, winsys manages the buffer and will
95501e04c3fSmrg       * free it on displaytarget_destroy. */
95601e04c3fSmrg      swr_fence_finish(p_screen, NULL, screen->flush_fence, 0);
95701e04c3fSmrg
95801e04c3fSmrg      struct sw_winsys *winsys = screen->winsys;
95901e04c3fSmrg      winsys->displaytarget_destroy(winsys, spr->display_target);
96001e04c3fSmrg
96101e04c3fSmrg      if (spr->swr.numSamples > 1) {
96201e04c3fSmrg         /* Free an attached resolve resource */
96301e04c3fSmrg         struct swr_resource *alt = swr_resource(spr->resolve_target);
96401e04c3fSmrg         swr_fence_work_free(screen->flush_fence, (void*)(alt->swr.xpBaseAddress), true);
96501e04c3fSmrg
96601e04c3fSmrg         /* Free multisample buffer */
96701e04c3fSmrg         swr_fence_work_free(screen->flush_fence, (void*)(spr->swr.xpBaseAddress), true);
96801e04c3fSmrg      }
96901e04c3fSmrg   } else {
97001e04c3fSmrg      /* For regular resources, defer deletion */
97101e04c3fSmrg      swr_resource_unused(pt);
97201e04c3fSmrg
97301e04c3fSmrg      if (spr->swr.numSamples > 1) {
97401e04c3fSmrg         /* Free an attached resolve resource */
97501e04c3fSmrg         struct swr_resource *alt = swr_resource(spr->resolve_target);
97601e04c3fSmrg         swr_fence_work_free(screen->flush_fence, (void*)(alt->swr.xpBaseAddress), true);
97701e04c3fSmrg      }
97801e04c3fSmrg
97901e04c3fSmrg      swr_fence_work_free(screen->flush_fence, (void*)(spr->swr.xpBaseAddress), true);
98001e04c3fSmrg      swr_fence_work_free(screen->flush_fence,
98101e04c3fSmrg                          (void*)(spr->secondary.xpBaseAddress), true);
98201e04c3fSmrg
98301e04c3fSmrg      /* If work queue grows too large, submit a fence to force queue to
98401e04c3fSmrg       * drain.  This is mainly to decrease the amount of memory used by the
98501e04c3fSmrg       * piglit streaming-texture-leak test */
98601e04c3fSmrg      if (screen->pipe && swr_fence(screen->flush_fence)->work.count > 64)
98701e04c3fSmrg         swr_fence_submit(swr_context(screen->pipe), screen->flush_fence);
98801e04c3fSmrg   }
98901e04c3fSmrg
99001e04c3fSmrg   FREE(spr);
99101e04c3fSmrg}
99201e04c3fSmrg
99301e04c3fSmrg
99401e04c3fSmrgstatic void
99501e04c3fSmrgswr_flush_frontbuffer(struct pipe_screen *p_screen,
9967ec681f3Smrg                      struct pipe_context *pipe,
99701e04c3fSmrg                      struct pipe_resource *resource,
99801e04c3fSmrg                      unsigned level,
99901e04c3fSmrg                      unsigned layer,
100001e04c3fSmrg                      void *context_private,
100101e04c3fSmrg                      struct pipe_box *sub_box)
100201e04c3fSmrg{
100301e04c3fSmrg   struct swr_screen *screen = swr_screen(p_screen);
100401e04c3fSmrg   struct sw_winsys *winsys = screen->winsys;
100501e04c3fSmrg   struct swr_resource *spr = swr_resource(resource);
100601e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
100701e04c3fSmrg
100801e04c3fSmrg   if (pipe) {
100901e04c3fSmrg      swr_fence_finish(p_screen, NULL, screen->flush_fence, 0);
101001e04c3fSmrg      swr_resource_unused(resource);
101101e04c3fSmrg      ctx->api.pfnSwrEndFrame(ctx->swrContext);
101201e04c3fSmrg   }
101301e04c3fSmrg
101401e04c3fSmrg   /* Multisample resolved into resolve_target at flush with store_resource */
101501e04c3fSmrg   if (pipe && spr->swr.numSamples > 1) {
101601e04c3fSmrg      struct pipe_resource *resolve_target = spr->resolve_target;
101701e04c3fSmrg
101801e04c3fSmrg      /* Once resolved, copy into display target */
101901e04c3fSmrg      SWR_SURFACE_STATE *resolve = &swr_resource(resolve_target)->swr;
102001e04c3fSmrg
102101e04c3fSmrg      void *map = winsys->displaytarget_map(winsys, spr->display_target,
10227ec681f3Smrg                                            PIPE_MAP_WRITE);
102301e04c3fSmrg      memcpy(map, (void*)(resolve->xpBaseAddress), resolve->pitch * resolve->height);
102401e04c3fSmrg      winsys->displaytarget_unmap(winsys, spr->display_target);
102501e04c3fSmrg   }
102601e04c3fSmrg
102701e04c3fSmrg   debug_assert(spr->display_target);
102801e04c3fSmrg   if (spr->display_target)
102901e04c3fSmrg      winsys->displaytarget_display(
103001e04c3fSmrg         winsys, spr->display_target, context_private, sub_box);
103101e04c3fSmrg}
103201e04c3fSmrg
103301e04c3fSmrg
103401e04c3fSmrgvoid
103501e04c3fSmrgswr_destroy_screen_internal(struct swr_screen **screen)
103601e04c3fSmrg{
103701e04c3fSmrg   struct pipe_screen *p_screen = &(*screen)->base;
103801e04c3fSmrg
103901e04c3fSmrg   swr_fence_finish(p_screen, NULL, (*screen)->flush_fence, 0);
104001e04c3fSmrg   swr_fence_reference(p_screen, &(*screen)->flush_fence, NULL);
104101e04c3fSmrg
104201e04c3fSmrg   JitDestroyContext((*screen)->hJitMgr);
104301e04c3fSmrg
104401e04c3fSmrg   if ((*screen)->pLibrary)
104501e04c3fSmrg      util_dl_close((*screen)->pLibrary);
104601e04c3fSmrg
104701e04c3fSmrg   FREE(*screen);
104801e04c3fSmrg   *screen = NULL;
104901e04c3fSmrg}
105001e04c3fSmrg
105101e04c3fSmrg
105201e04c3fSmrgstatic void
105301e04c3fSmrgswr_destroy_screen(struct pipe_screen *p_screen)
105401e04c3fSmrg{
105501e04c3fSmrg   struct swr_screen *screen = swr_screen(p_screen);
105601e04c3fSmrg   struct sw_winsys *winsys = screen->winsys;
105701e04c3fSmrg
10587ec681f3Smrg   swr_print_info("SWR destroy screen!\n");
105901e04c3fSmrg
106001e04c3fSmrg   if (winsys->destroy)
106101e04c3fSmrg      winsys->destroy(winsys);
106201e04c3fSmrg
106301e04c3fSmrg   swr_destroy_screen_internal(&screen);
106401e04c3fSmrg}
106501e04c3fSmrg
106601e04c3fSmrg
106701e04c3fSmrgstatic void
106801e04c3fSmrgswr_validate_env_options(struct swr_screen *screen)
106901e04c3fSmrg{
107001e04c3fSmrg   /* The client_copy_limit sets a maximum on the amount of user-buffer memory
107101e04c3fSmrg    * copied to scratch space on a draw.  Past this, the draw will access
107201e04c3fSmrg    * user-buffer directly and then block.  This is faster than queuing many
107301e04c3fSmrg    * large client draws. */
107401e04c3fSmrg   screen->client_copy_limit = SWR_CLIENT_COPY_LIMIT;
107501e04c3fSmrg   int client_copy_limit =
107601e04c3fSmrg      debug_get_num_option("SWR_CLIENT_COPY_LIMIT", SWR_CLIENT_COPY_LIMIT);
107701e04c3fSmrg   if (client_copy_limit > 0)
107801e04c3fSmrg      screen->client_copy_limit = client_copy_limit;
107901e04c3fSmrg
108001e04c3fSmrg   /* XXX msaa under development, disable by default for now */
108101e04c3fSmrg   screen->msaa_max_count = 1; /* was SWR_MAX_NUM_MULTISAMPLES; */
108201e04c3fSmrg
108301e04c3fSmrg   /* validate env override values, within range and power of 2 */
108401e04c3fSmrg   int msaa_max_count = debug_get_num_option("SWR_MSAA_MAX_COUNT", 1);
108501e04c3fSmrg   if (msaa_max_count != 1) {
108601e04c3fSmrg      if ((msaa_max_count < 1) || (msaa_max_count > SWR_MAX_NUM_MULTISAMPLES)
108701e04c3fSmrg            || !util_is_power_of_two_or_zero(msaa_max_count)) {
108801e04c3fSmrg         fprintf(stderr, "SWR_MSAA_MAX_COUNT invalid: %d\n", msaa_max_count);
108901e04c3fSmrg         fprintf(stderr, "must be power of 2 between 1 and %d" \
109001e04c3fSmrg                         " (or 1 to disable msaa)\n",
109101e04c3fSmrg               SWR_MAX_NUM_MULTISAMPLES);
10927ec681f3Smrg         fprintf(stderr, "(msaa disabled)\n");
109301e04c3fSmrg         msaa_max_count = 1;
109401e04c3fSmrg      }
109501e04c3fSmrg
10967ec681f3Smrg      swr_print_info("SWR_MSAA_MAX_COUNT: %d\n", msaa_max_count);
109701e04c3fSmrg
109801e04c3fSmrg      screen->msaa_max_count = msaa_max_count;
109901e04c3fSmrg   }
110001e04c3fSmrg
110101e04c3fSmrg   screen->msaa_force_enable = debug_get_bool_option(
110201e04c3fSmrg         "SWR_MSAA_FORCE_ENABLE", false);
110301e04c3fSmrg   if (screen->msaa_force_enable)
11047ec681f3Smrg      swr_print_info("SWR_MSAA_FORCE_ENABLE: true\n");
110501e04c3fSmrg}
110601e04c3fSmrg
110701e04c3fSmrg
110801e04c3fSmrgstruct pipe_screen *
110901e04c3fSmrgswr_create_screen_internal(struct sw_winsys *winsys)
111001e04c3fSmrg{
111101e04c3fSmrg   struct swr_screen *screen = CALLOC_STRUCT(swr_screen);
111201e04c3fSmrg
111301e04c3fSmrg   if (!screen)
111401e04c3fSmrg      return NULL;
111501e04c3fSmrg
111601e04c3fSmrg   if (!lp_build_init()) {
111701e04c3fSmrg      FREE(screen);
111801e04c3fSmrg      return NULL;
111901e04c3fSmrg   }
112001e04c3fSmrg
112101e04c3fSmrg   screen->winsys = winsys;
112201e04c3fSmrg   screen->base.get_name = swr_get_name;
112301e04c3fSmrg   screen->base.get_vendor = swr_get_vendor;
112401e04c3fSmrg   screen->base.is_format_supported = swr_is_format_supported;
112501e04c3fSmrg   screen->base.context_create = swr_create_context;
112601e04c3fSmrg   screen->base.can_create_resource = swr_can_create_resource;
112701e04c3fSmrg
112801e04c3fSmrg   screen->base.destroy = swr_destroy_screen;
112901e04c3fSmrg   screen->base.get_param = swr_get_param;
113001e04c3fSmrg   screen->base.get_shader_param = swr_get_shader_param;
113101e04c3fSmrg   screen->base.get_paramf = swr_get_paramf;
113201e04c3fSmrg
113301e04c3fSmrg   screen->base.resource_create = swr_resource_create;
113401e04c3fSmrg   screen->base.resource_destroy = swr_resource_destroy;
113501e04c3fSmrg
113601e04c3fSmrg   screen->base.flush_frontbuffer = swr_flush_frontbuffer;
113701e04c3fSmrg
113801e04c3fSmrg   // Pass in "" for architecture for run-time determination
113901e04c3fSmrg   screen->hJitMgr = JitCreateContext(KNOB_SIMD_WIDTH, "", "swr");
114001e04c3fSmrg
114101e04c3fSmrg   swr_fence_init(&screen->base);
114201e04c3fSmrg
114301e04c3fSmrg   swr_validate_env_options(screen);
114401e04c3fSmrg
114501e04c3fSmrg   return &screen->base;
114601e04c3fSmrg}
1147