Merge branch 'draw-instanced'
[mesa.git] / src / gallium / drivers / llvmpipe / lp_screen.c
index 6d309c6b6474741b95d2d3be2b01649cd3ff415a..b6919a5c6d3d19470e3203a90e3a786b2ff69819 100644 (file)
 
 
 #include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_cpu_detect.h"
 #include "util/u_format.h"
 #include "util/u_format_s3tc.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_screen.h"
+#include "draw/draw_context.h"
 
 #include "lp_texture.h"
 #include "lp_fence.h"
@@ -39,6 +42,8 @@
 #include "lp_context.h"
 #include "lp_debug.h"
 #include "lp_public.h"
+#include "lp_limits.h"
+#include "lp_rast.h"
 
 #include "state_tracker/sw_winsys.h"
 
 int LP_DEBUG = 0;
 
 static const struct debug_named_value lp_debug_flags[] = {
-   { "pipe",   DEBUG_PIPE },
-   { "tgsi",   DEBUG_TGSI },
-   { "tex",    DEBUG_TEX },
-   { "asm",    DEBUG_ASM },
-   { "setup",  DEBUG_SETUP },
-   { "rast",   DEBUG_RAST },
-   { "query",  DEBUG_QUERY },
-   { "screen", DEBUG_SCREEN },
-   { "jit",    DEBUG_JIT },
-   { "show_tiles",    DEBUG_SHOW_TILES },
-   { "show_subtiles", DEBUG_SHOW_SUBTILES },
-   { "counters", DEBUG_COUNTERS },
-   { "nopt", DEBUG_NO_LLVM_OPT },
-   {NULL, 0}
+   { "pipe",   DEBUG_PIPE, NULL },
+   { "tgsi",   DEBUG_TGSI, NULL },
+   { "tex",    DEBUG_TEX, NULL },
+   { "setup",  DEBUG_SETUP, NULL },
+   { "rast",   DEBUG_RAST, NULL },
+   { "query",  DEBUG_QUERY, NULL },
+   { "screen", DEBUG_SCREEN, NULL },
+   { "show_tiles",    DEBUG_SHOW_TILES, NULL },
+   { "show_subtiles", DEBUG_SHOW_SUBTILES, NULL },
+   { "counters", DEBUG_COUNTERS, NULL },
+   { "scene", DEBUG_SCENE, NULL },
+   { "fence", DEBUG_FENCE, NULL },
+   { "mem", DEBUG_MEM, NULL },
+   { "fs", DEBUG_FS, NULL },
+   DEBUG_NAMED_VALUE_END
 };
 #endif
 
+int LP_PERF = 0;
+static const struct debug_named_value lp_perf_flags[] = {
+   { "texmem",         PERF_TEX_MEM, NULL },
+   { "no_mipmap",      PERF_NO_MIPMAPS, NULL },
+   { "no_linear",      PERF_NO_LINEAR, NULL },
+   { "no_mip_linear",  PERF_NO_MIP_LINEAR, NULL },
+   { "no_tex",         PERF_NO_TEX, NULL },
+   { "no_blend",       PERF_NO_BLEND, NULL },
+   { "no_depth",       PERF_NO_DEPTH, NULL },
+   { "no_alphatest",   PERF_NO_ALPHATEST, NULL },
+   DEBUG_NAMED_VALUE_END
+};
+
 
 static const char *
 llvmpipe_get_vendor(struct pipe_screen *screen)
@@ -79,13 +98,20 @@ llvmpipe_get_name(struct pipe_screen *screen)
 
 
 static int
-llvmpipe_get_param(struct pipe_screen *screen, int param)
+llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
 {
    switch (param) {
    case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
       return PIPE_MAX_SAMPLERS;
    case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
-      return 0;
+      /* At this time, the draw module and llvmpipe driver only
+       * support vertex shader texture lookups when LLVM is enabled in
+       * the draw module.
+       */
+      if (debug_get_bool_option("DRAW_USE_LLVM", TRUE))
+         return PIPE_MAX_VERTEX_SAMPLERS;
+      else
+         return 0;
    case PIPE_CAP_MAX_COMBINED_SAMPLERS:
       return PIPE_MAX_SAMPLERS + PIPE_MAX_VERTEX_SAMPLERS;
    case PIPE_CAP_NPOT_TEXTURES:
@@ -94,6 +120,8 @@ llvmpipe_get_param(struct pipe_screen *screen, int param)
       return 1;
    case PIPE_CAP_GLSL:
       return 1;
+   case PIPE_CAP_SM3:
+      return 1;
    case PIPE_CAP_ANISOTROPIC_FILTER:
       return 0;
    case PIPE_CAP_POINT_SPRITE:
@@ -102,24 +130,26 @@ llvmpipe_get_param(struct pipe_screen *screen, int param)
       return PIPE_MAX_COLOR_BUFS;
    case PIPE_CAP_OCCLUSION_QUERY:
       return 1;
+   case PIPE_CAP_TIMER_QUERY:
+      return 0;
    case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
       return 1;
    case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
       return 1;
    case PIPE_CAP_TEXTURE_SHADOW_MAP:
       return 1;
+   case PIPE_CAP_TEXTURE_SWIZZLE:
+      return 1;
    case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
       return LP_MAX_TEXTURE_2D_LEVELS;
    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
       return LP_MAX_TEXTURE_3D_LEVELS;
    case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
       return LP_MAX_TEXTURE_2D_LEVELS;
-   case PIPE_CAP_TGSI_CONT_SUPPORTED:
-      return 1;
    case PIPE_CAP_BLEND_EQUATION_SEPARATE:
       return 1;
    case PIPE_CAP_INDEP_BLEND_ENABLE:
-      return 0;
+      return 1;
    case PIPE_CAP_INDEP_BLEND_FUNC:
       return 0;
    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
@@ -128,14 +158,36 @@ llvmpipe_get_param(struct pipe_screen *screen, int param)
    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
       return 0;
+   case PIPE_CAP_PRIMITIVE_RESTART:
+      return 1;
+   case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
+      return 1;
+   case PIPE_CAP_DEPTH_CLAMP:
+      return 0;
+   case PIPE_CAP_INSTANCED_DRAWING:
+      return 1;
    default:
       return 0;
    }
 }
 
+static int
+llvmpipe_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param)
+{
+   switch(shader)
+   {
+   case PIPE_SHADER_FRAGMENT:
+      return tgsi_exec_get_shader_param(param);
+   case PIPE_SHADER_VERTEX:
+   case PIPE_SHADER_GEOMETRY:
+      return draw_get_shader_param(shader, param);
+   default:
+      return 0;
+   }
+}
 
 static float
-llvmpipe_get_paramf(struct pipe_screen *screen, int param)
+llvmpipe_get_paramf(struct pipe_screen *screen, enum pipe_cap param)
 {
    switch (param) {
    case PIPE_CAP_MAX_LINE_WIDTH:
@@ -150,7 +202,13 @@ llvmpipe_get_paramf(struct pipe_screen *screen, int param)
       return 16.0; /* not actually signficant at this time */
    case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
       return 16.0; /* arbitrary */
+   case PIPE_CAP_GUARD_BAND_LEFT:
+   case PIPE_CAP_GUARD_BAND_TOP:
+   case PIPE_CAP_GUARD_BAND_RIGHT:
+   case PIPE_CAP_GUARD_BAND_BOTTOM:
+      return 0.0;
    default:
+      assert(0);
       return 0;
    }
 }
@@ -163,9 +221,10 @@ llvmpipe_get_paramf(struct pipe_screen *screen, int param)
  */
 static boolean
 llvmpipe_is_format_supported( struct pipe_screen *_screen,
-                              enum pipe_format format, 
+                              enum pipe_format format,
                               enum pipe_texture_target target,
-                              unsigned tex_usage, 
+                              unsigned sample_count,
+                              unsigned bind,
                               unsigned geom_flags )
 {
    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
@@ -173,53 +232,55 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen,
    const struct util_format_description *format_desc;
 
    format_desc = util_format_description(format);
-   if(!format_desc)
+   if (!format_desc)
       return FALSE;
 
-   assert(target == PIPE_TEXTURE_1D ||
+   assert(target == PIPE_BUFFER ||
+          target == PIPE_TEXTURE_1D ||
           target == PIPE_TEXTURE_2D ||
+          target == PIPE_TEXTURE_RECT ||
           target == PIPE_TEXTURE_3D ||
           target == PIPE_TEXTURE_CUBE);
 
-   switch(format) {
-   case PIPE_FORMAT_DXT1_RGB:
-   case PIPE_FORMAT_DXT1_RGBA:
-   case PIPE_FORMAT_DXT3_RGBA:
-   case PIPE_FORMAT_DXT5_RGBA:
-      return util_format_s3tc_enabled;
-   default:
-      break;
-   }
+   if (sample_count > 1)
+      return FALSE;
 
-   if(tex_usage & PIPE_BIND_RENDER_TARGET) {
-      if(format_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN)
+   if (bind & PIPE_BIND_RENDER_TARGET) {
+      if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
          return FALSE;
 
-      if(format_desc->block.width != 1 ||
-         format_desc->block.height != 1)
+      if (format_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN)
          return FALSE;
 
-      if(format_desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB &&
-         format_desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB)
+      if (format_desc->block.width != 1 ||
+          format_desc->block.height != 1)
          return FALSE;
    }
 
-   if(tex_usage & (PIPE_BIND_DISPLAY_TARGET |
-                   PIPE_BIND_SCANOUT |
-                   PIPE_BIND_SHARED)) {
-      if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
+   if (bind & PIPE_BIND_DISPLAY_TARGET) {
+      if(!winsys->is_displaytarget_format_supported(winsys, bind, format))
          return FALSE;
    }
 
-   if(tex_usage & PIPE_BIND_DEPTH_STENCIL) {
-      if(format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
+   if (bind & PIPE_BIND_DEPTH_STENCIL) {
+      if (format_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN)
+         return FALSE;
+
+      if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
          return FALSE;
 
       /* FIXME: Temporary restriction. See lp_state_fs.c. */
-      if(format_desc->block.bits != 32)
+      if (format_desc->block.bits != 32)
          return FALSE;
    }
 
+   if (format_desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
+      return util_format_s3tc_enabled;
+   }
+
+   /*
+    * Everything else should be supported by u_format.
+    */
    return TRUE;
 }
 
@@ -228,12 +289,13 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen,
 
 static void
 llvmpipe_flush_frontbuffer(struct pipe_screen *_screen,
-                           struct pipe_surface *surface,
+                           struct pipe_resource *resource,
+                           unsigned level, unsigned layer,
                            void *context_private)
 {
    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
    struct sw_winsys *winsys = screen->winsys;
-   struct llvmpipe_resource *texture = llvmpipe_resource(surface->texture);
+   struct llvmpipe_resource *texture = llvmpipe_resource(resource);
 
    assert(texture->dt);
    if (texture->dt)
@@ -247,16 +309,66 @@ llvmpipe_destroy_screen( struct pipe_screen *_screen )
    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
    struct sw_winsys *winsys = screen->winsys;
 
+   if (screen->rast)
+      lp_rast_destroy(screen->rast);
+
    lp_jit_screen_cleanup(screen);
 
    if(winsys->destroy)
       winsys->destroy(winsys);
 
+   pipe_mutex_destroy(screen->rast_mutex);
+
    FREE(screen);
 }
 
 
 
+
+/**
+ * Fence reference counting.
+ */
+static void
+llvmpipe_fence_reference(struct pipe_screen *screen,
+                         struct pipe_fence_handle **ptr,
+                         struct pipe_fence_handle *fence)
+{
+   struct lp_fence **old = (struct lp_fence **) ptr;
+   struct lp_fence *f = (struct lp_fence *) fence;
+
+   lp_fence_reference(old, f);
+}
+
+
+/**
+ * Has the fence been executed/finished?
+ */
+static int
+llvmpipe_fence_signalled(struct pipe_screen *screen,
+                         struct pipe_fence_handle *fence,
+                         unsigned flag)
+{
+   struct lp_fence *f = (struct lp_fence *) fence;
+   return lp_fence_signalled(f);
+}
+
+
+/**
+ * Wait for the fence to finish.
+ */
+static int
+llvmpipe_fence_finish(struct pipe_screen *screen,
+                      struct pipe_fence_handle *fence_handle,
+                      unsigned flag)
+{
+   struct lp_fence *f = (struct lp_fence *) fence_handle;
+
+   lp_fence_wait(f);
+   return 0;
+}
+
+
+
 /**
  * Create a new pipe_screen object
  * Note: we're not presently subclassing pipe_screen (no llvmpipe_screen).
@@ -264,12 +376,23 @@ llvmpipe_destroy_screen( struct pipe_screen *_screen )
 struct pipe_screen *
 llvmpipe_create_screen(struct sw_winsys *winsys)
 {
-   struct llvmpipe_screen *screen = CALLOC_STRUCT(llvmpipe_screen);
+   struct llvmpipe_screen *screen;
+
+#ifdef PIPE_ARCH_X86
+   /* require SSE2 due to LLVM PR6960. */
+   util_cpu_detect();
+   if (!util_cpu_caps.has_sse2)
+       return NULL;
+#endif
+
+   screen = CALLOC_STRUCT(llvmpipe_screen);
 
 #ifdef DEBUG
    LP_DEBUG = debug_get_flags_option("LP_DEBUG", lp_debug_flags, 0 );
 #endif
 
+   LP_PERF = debug_get_flags_option("LP_PERF", lp_perf_flags, 0 );
+
    if (!screen)
       return NULL;
 
@@ -280,18 +403,36 @@ llvmpipe_create_screen(struct sw_winsys *winsys)
    screen->base.get_name = llvmpipe_get_name;
    screen->base.get_vendor = llvmpipe_get_vendor;
    screen->base.get_param = llvmpipe_get_param;
+   screen->base.get_shader_param = llvmpipe_get_shader_param;
    screen->base.get_paramf = llvmpipe_get_paramf;
    screen->base.is_format_supported = llvmpipe_is_format_supported;
 
    screen->base.context_create = llvmpipe_create_context;
    screen->base.flush_frontbuffer = llvmpipe_flush_frontbuffer;
-
-   util_format_s3tc_init();
+   screen->base.fence_reference = llvmpipe_fence_reference;
+   screen->base.fence_signalled = llvmpipe_fence_signalled;
+   screen->base.fence_finish = llvmpipe_fence_finish;
 
    llvmpipe_init_screen_resource_funcs(&screen->base);
-   llvmpipe_init_screen_fence_funcs(&screen->base);
 
    lp_jit_screen_init(screen);
 
+   screen->num_threads = util_cpu_caps.nr_cpus > 1 ? util_cpu_caps.nr_cpus : 0;
+#ifdef PIPE_OS_EMBEDDED
+   screen->num_threads = 0;
+#endif
+   screen->num_threads = debug_get_num_option("LP_NUM_THREADS", screen->num_threads);
+   screen->num_threads = MIN2(screen->num_threads, LP_MAX_THREADS);
+
+   screen->rast = lp_rast_create(screen->num_threads);
+   if (!screen->rast) {
+      lp_jit_screen_cleanup(screen);
+      FREE(screen);
+      return NULL;
+   }
+   pipe_mutex_init(screen->rast_mutex);
+
+   util_format_s3tc_init();
+
    return &screen->base;
 }