gallium: remove PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_ATTRIBS
[mesa.git] / src / gallium / drivers / r600 / r600_pipe.c
index d180e36aa162ee93fd759dcde59f2413ed282b83..7f62e0e1c69d92ddf20a6a54d79d14af0da32183 100644 (file)
  */
 #include <stdio.h>
 #include <errno.h>
-#include <pipe/p_defines.h>
-#include <pipe/p_state.h>
-#include <pipe/p_context.h>
-#include <tgsi/tgsi_scan.h>
-#include <tgsi/tgsi_parse.h>
-#include <tgsi/tgsi_util.h>
-#include <util/u_blitter.h>
-#include <util/u_double_list.h>
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_context.h"
+#include "tgsi/tgsi_scan.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "util/u_blitter.h"
+#include "util/u_double_list.h"
 #include "util/u_format.h"
-#include <util/u_format_s3tc.h>
-#include <util/u_transfer.h>
-#include <util/u_surface.h>
-#include <util/u_pack_color.h>
-#include <util/u_memory.h>
-#include <util/u_inlines.h>
+#include "util/u_format_s3tc.h"
+#include "util/u_transfer.h"
+#include "util/u_surface.h"
+#include "util/u_pack_color.h"
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
 #include "util/u_upload_mgr.h"
-#include <vl/vl_decoder.h>
-#include <vl/vl_video_buffer.h>
+#include "vl/vl_decoder.h"
+#include "vl/vl_video_buffer.h"
 #include "os/os_time.h"
-#include <pipebuffer/pb_buffer.h>
+#include "pipebuffer/pb_buffer.h"
 #include "r600.h"
 #include "r600d.h"
 #include "r600_resource.h"
 #include "r600_shader.h"
 #include "r600_pipe.h"
-#include "../../winsys/r600/drm/r600_drm_public.h"
 
 /*
  * pipe_context
  */
 static struct r600_fence *r600_create_fence(struct r600_pipe_context *ctx)
 {
-       struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
        struct r600_fence *fence = NULL;
 
        if (!ctx->fences.bo) {
                /* Create the shared buffer object */
-               ctx->fences.bo = r600_bo(ctx->radeon, 4096, 0, 0, 0);
+               ctx->fences.bo = (struct r600_resource*)
+                       pipe_buffer_create(&ctx->screen->screen, PIPE_BIND_CUSTOM,
+                                          PIPE_USAGE_STAGING, 4096);
                if (!ctx->fences.bo) {
                        R600_ERR("r600: failed to create bo for fence objects\n");
                        return NULL;
                }
-               ctx->fences.data = r600_bo_map(ctx->radeon, ctx->fences.bo, rctx->ctx.cs,
-                                              PIPE_TRANSFER_UNSYNCHRONIZED | PIPE_TRANSFER_WRITE);
+               ctx->fences.data = ctx->ws->buffer_map(ctx->fences.bo->buf, ctx->ctx.cs,
+                                                      PIPE_TRANSFER_WRITE);
        }
 
        if (!LIST_IS_EMPTY(&ctx->fences.pool)) {
@@ -122,11 +122,25 @@ void r600_flush(struct pipe_context *ctx, struct pipe_fence_handle **fence,
 {
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
        struct r600_fence **rfence = (struct r600_fence**)fence;
+       struct pipe_query *render_cond = NULL;
+       unsigned render_cond_mode = 0;
 
        if (rfence)
                *rfence = r600_create_fence(rctx);
 
+       /* Disable render condition. */
+       if (rctx->current_render_cond) {
+               render_cond = rctx->current_render_cond;
+               render_cond_mode = rctx->current_render_cond_mode;
+               ctx->render_condition(ctx, NULL, 0);
+       }
+
        r600_context_flush(&rctx->ctx, flags);
+
+       /* Re-enable render condition. */
+       if (render_cond) {
+               ctx->render_condition(ctx, render_cond, render_cond_mode);
+       }
 }
 
 static void r600_flush_from_st(struct pipe_context *ctx,
@@ -174,7 +188,7 @@ static void r600_destroy_context(struct pipe_context *context)
                free(rctx->states[i]);
        }
 
-       u_vbuf_mgr_destroy(rctx->vbuf_mgr);
+       u_vbuf_destroy(rctx->vbuf_mgr);
        util_slab_destroy(&rctx->pool_transfers);
 
        if (rctx->fences.bo) {
@@ -185,8 +199,8 @@ static void r600_destroy_context(struct pipe_context *context)
                        FREE(entry);
                }
 
-               r600_bo_unmap(rctx->radeon, rctx->fences.bo);
-               r600_bo_reference(&rctx->fences.bo, NULL);
+               rctx->ws->buffer_unmap(rctx->fences.bo->buf);
+               pipe_resource_reference((struct pipe_resource**)&rctx->fences.bo, NULL);
        }
 
        r600_update_num_contexts(rctx->screen, -1);
@@ -212,9 +226,9 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 
        /* Easy accessing of screen/winsys. */
        rctx->screen = rscreen;
-       rctx->radeon = rscreen->radeon;
-       rctx->family = r600_get_family(rctx->radeon);
-       rctx->chip_class = r600_get_family_class(rctx->radeon);
+       rctx->ws = rscreen->ws;
+       rctx->family = rscreen->family;
+       rctx->chip_class = rscreen->chip_class;
 
        rctx->fences.bo = NULL;
        rctx->fences.data = NULL;
@@ -235,7 +249,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
        case R600:
        case R700:
                r600_init_state_functions(rctx);
-               if (r600_context_init(&rctx->ctx, rctx->radeon)) {
+               if (r600_context_init(&rctx->ctx, rctx->screen)) {
                        r600_destroy_context(&rctx->context);
                        return NULL;
                }
@@ -245,7 +259,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
        case EVERGREEN:
        case CAYMAN:
                evergreen_init_state_functions(rctx);
-               if (evergreen_context_init(&rctx->ctx, rctx->radeon)) {
+               if (evergreen_context_init(&rctx->ctx, rctx->screen)) {
                        r600_destroy_context(&rctx->context);
                        return NULL;
                }
@@ -258,13 +272,15 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
                return NULL;
        }
 
-       rctx->screen->ws->cs_set_flush_callback(rctx->ctx.cs, r600_flush_from_winsys, rctx);
+       rctx->ctx.pipe = &rctx->context;
+       rctx->ctx.flush = r600_flush_from_winsys;
+       rctx->ws->cs_set_flush_callback(rctx->ctx.cs, r600_flush_from_winsys, rctx);
 
        util_slab_create(&rctx->pool_transfers,
                         sizeof(struct pipe_transfer), 64,
                         UTIL_SLAB_SINGLETHREADED);
 
-       rctx->vbuf_mgr = u_vbuf_mgr_create(&rctx->context, 1024 * 1024, 256,
+       rctx->vbuf_mgr = u_vbuf_create(&rctx->context, 1024 * 1024, 256,
                                           PIPE_BIND_VERTEX_BUFFER |
                                           PIPE_BIND_INDEX_BUFFER |
                                           PIPE_BIND_CONSTANT_BUFFER,
@@ -281,6 +297,8 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
                return NULL;
        }
 
+       r600_get_backend_mask(&rctx->ctx); /* this emits commands and must be last */
+
        return &rctx->context;
 }
 
@@ -326,28 +344,25 @@ static const char *r600_get_family_name(enum radeon_family family)
 static const char* r600_get_name(struct pipe_screen* pscreen)
 {
        struct r600_screen *rscreen = (struct r600_screen *)pscreen;
-       enum radeon_family family = r600_get_family(rscreen->radeon);
 
-       return r600_get_family_name(family);
+       return r600_get_family_name(rscreen->family);
 }
 
 static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 {
        struct r600_screen *rscreen = (struct r600_screen *)pscreen;
-       enum radeon_family family = r600_get_family(rscreen->radeon);
+       enum radeon_family family = rscreen->family;
 
        switch (param) {
        /* Supported features (boolean caps). */
        case PIPE_CAP_NPOT_TEXTURES:
        case PIPE_CAP_TWO_SIDED_STENCIL:
-       case PIPE_CAP_GLSL:
        case PIPE_CAP_DUAL_SOURCE_BLEND:
        case PIPE_CAP_ANISOTROPIC_FILTER:
        case PIPE_CAP_POINT_SPRITE:
        case PIPE_CAP_OCCLUSION_QUERY:
        case PIPE_CAP_TEXTURE_SHADOW_MAP:
        case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
-       case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
        case PIPE_CAP_BLEND_EQUATION_SEPARATE:
        case PIPE_CAP_TEXTURE_SWIZZLE:
        case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
@@ -361,6 +376,9 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
        case PIPE_CAP_SEAMLESS_CUBE_MAP:
        case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL:
        case PIPE_CAP_PRIMITIVE_RESTART:
+       case PIPE_CAP_CONDITIONAL_RENDER:
+       case PIPE_CAP_TEXTURE_BARRIER:
+       case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
                return 1;
 
        /* Supported except the original R600. */
@@ -374,15 +392,20 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
                return family >= CHIP_CEDAR ? 1 : 0;
 
        /* Unsupported features. */
-       case PIPE_CAP_STREAM_OUTPUT:
        case PIPE_CAP_TGSI_INSTANCEID:
        case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
        case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
+       case PIPE_CAP_SCALED_RESOLVE:
+       case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
+       case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
                return 0;
 
-       case PIPE_CAP_ARRAY_TEXTURES:
-               /* fix once the CS checker upstream is fixed */
-               return debug_get_bool_option("R600_ARRAY_TEXTURE", FALSE);
+       /* Stream output. */
+       case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
+               return debug_get_bool_option("R600_STREAMOUT", FALSE) ? 4 : 0;
+       case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
+       case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
+               return 16*4;
 
        /* Texturing. */
        case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
@@ -392,9 +415,9 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
                        return 15;
                else
                        return 14;
-       case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
-       case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
-               return 16;
+       case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
+               return rscreen->info.drm_minor >= 9 ?
+                       (family >= CHIP_CEDAR ? 16384 : 8192) : 0;
        case PIPE_CAP_MAX_COMBINED_SAMPLERS:
                return 32;
 
@@ -405,40 +428,48 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 
        /* Timer queries, present when the clock frequency is non zero. */
        case PIPE_CAP_TIMER_QUERY:
-               return r600_get_clock_crystal_freq(rscreen->radeon) != 0;
+               return rscreen->info.r600_clock_crystal_freq != 0;
 
-       default:
-               R600_ERR("r600: unknown param %d\n", param);
-               return 0;
+       case PIPE_CAP_MIN_TEXEL_OFFSET:
+               return -8;
+
+       case PIPE_CAP_MAX_TEXEL_OFFSET:
+               return 7;
        }
+       return 0;
 }
 
-static float r600_get_paramf(struct pipe_screen* pscreen, enum pipe_cap param)
+static float r600_get_paramf(struct pipe_screen* pscreen,
+                            enum pipe_capf param)
 {
        struct r600_screen *rscreen = (struct r600_screen *)pscreen;
-       enum radeon_family family = r600_get_family(rscreen->radeon);
+       enum radeon_family family = rscreen->family;
 
        switch (param) {
-       case PIPE_CAP_MAX_LINE_WIDTH:
-       case PIPE_CAP_MAX_LINE_WIDTH_AA:
-       case PIPE_CAP_MAX_POINT_WIDTH:
-       case PIPE_CAP_MAX_POINT_WIDTH_AA:
+       case PIPE_CAPF_MAX_LINE_WIDTH:
+       case PIPE_CAPF_MAX_LINE_WIDTH_AA:
+       case PIPE_CAPF_MAX_POINT_WIDTH:
+       case PIPE_CAPF_MAX_POINT_WIDTH_AA:
                if (family >= CHIP_CEDAR)
                        return 16384.0f;
                else
                        return 8192.0f;
-       case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+       case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
                return 16.0f;
-       case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+       case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
                return 16.0f;
-       default:
-               R600_ERR("r600: unsupported paramf %d\n", param);
+       case PIPE_CAPF_GUARD_BAND_LEFT:
+       case PIPE_CAPF_GUARD_BAND_TOP:
+       case PIPE_CAPF_GUARD_BAND_RIGHT:
+       case PIPE_CAPF_GUARD_BAND_BOTTOM:
                return 0.0f;
        }
+       return 0.0f;
 }
 
 static int r600_get_shader_param(struct pipe_screen* pscreen, unsigned shader, enum pipe_shader_cap param)
 {
+       struct r600_screen *rscreen = (struct r600_screen *)pscreen;
        switch(shader)
        {
        case PIPE_SHADER_FRAGMENT:
@@ -487,10 +518,15 @@ static int r600_get_shader_param(struct pipe_screen* pscreen, unsigned shader, e
        case PIPE_SHADER_CAP_SUBROUTINES:
                return 0;
        case PIPE_SHADER_CAP_INTEGERS:
+               if (rscreen->chip_class == EVERGREEN)
+                       return 1;
                return 0;
-       default:
-               return 0;
+       case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
+               return 16;
+       case PIPE_SHADER_CAP_OUTPUT_READ:
+               return 1;
        }
+       return 0;
 }
 
 static int r600_get_video_param(struct pipe_screen *screen,
@@ -505,6 +541,8 @@ static int r600_get_video_param(struct pipe_screen *screen,
        case PIPE_VIDEO_CAP_MAX_WIDTH:
        case PIPE_VIDEO_CAP_MAX_HEIGHT:
                return vl_video_buffer_max_size(screen);
+       case PIPE_VIDEO_CAP_NUM_BUFFERS_DESIRED:
+               return vl_num_buffers_desired(screen, profile);
        default:
                return 0;
        }
@@ -517,7 +555,6 @@ static void r600_destroy_screen(struct pipe_screen* pscreen)
        if (rscreen == NULL)
                return;
 
-       radeon_destroy(rscreen->radeon);
        rscreen->ws->destroy(rscreen->ws);
 
        util_slab_destroy(&rscreen->pool_buffers);
@@ -582,18 +619,160 @@ static boolean r600_fence_finish(struct pipe_screen *pscreen,
        return TRUE;
 }
 
-struct pipe_screen *r600_screen_create(struct radeon_winsys *ws)
+static int r600_interpret_tiling(struct r600_screen *rscreen, uint32_t tiling_config)
+{
+       switch ((tiling_config & 0xe) >> 1) {
+       case 0:
+               rscreen->tiling_info.num_channels = 1;
+               break;
+       case 1:
+               rscreen->tiling_info.num_channels = 2;
+               break;
+       case 2:
+               rscreen->tiling_info.num_channels = 4;
+               break;
+       case 3:
+               rscreen->tiling_info.num_channels = 8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch ((tiling_config & 0x30) >> 4) {
+       case 0:
+               rscreen->tiling_info.num_banks = 4;
+               break;
+       case 1:
+               rscreen->tiling_info.num_banks = 8;
+               break;
+       default:
+               return -EINVAL;
+
+       }
+       switch ((tiling_config & 0xc0) >> 6) {
+       case 0:
+               rscreen->tiling_info.group_bytes = 256;
+               break;
+       case 1:
+               rscreen->tiling_info.group_bytes = 512;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int evergreen_interpret_tiling(struct r600_screen *rscreen, uint32_t tiling_config)
+{
+       switch (tiling_config & 0xf) {
+       case 0:
+               rscreen->tiling_info.num_channels = 1;
+               break;
+       case 1:
+               rscreen->tiling_info.num_channels = 2;
+               break;
+       case 2:
+               rscreen->tiling_info.num_channels = 4;
+               break;
+       case 3:
+               rscreen->tiling_info.num_channels = 8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch ((tiling_config & 0xf0) >> 4) {
+       case 0:
+               rscreen->tiling_info.num_banks = 4;
+               break;
+       case 1:
+               rscreen->tiling_info.num_banks = 8;
+               break;
+       case 2:
+               rscreen->tiling_info.num_banks = 16;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch ((tiling_config & 0xf00) >> 8) {
+       case 0:
+               rscreen->tiling_info.group_bytes = 256;
+               break;
+       case 1:
+               rscreen->tiling_info.group_bytes = 512;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int r600_init_tiling(struct r600_screen *rscreen)
 {
-       struct r600_screen *rscreen;
-       struct radeon *radeon = radeon_create(ws);
+       uint32_t tiling_config = rscreen->info.r600_tiling_config;
+
+       /* set default group bytes, overridden by tiling info ioctl */
+       if (rscreen->chip_class <= R700) {
+               rscreen->tiling_info.group_bytes = 256;
+       } else {
+               rscreen->tiling_info.group_bytes = 512;
+       }
 
-       rscreen = CALLOC_STRUCT(r600_screen);
+       if (!tiling_config)
+               return 0;
+
+       if (rscreen->chip_class <= R700) {
+               return r600_interpret_tiling(rscreen, tiling_config);
+       } else {
+               return evergreen_interpret_tiling(rscreen, tiling_config);
+       }
+}
+
+static unsigned radeon_family_from_device(unsigned device)
+{
+       switch (device) {
+#define CHIPSET(pciid, name, family) case pciid: return CHIP_##family;
+#include "pci_ids/r600_pci_ids.h"
+#undef CHIPSET
+       default:
+               return CHIP_UNKNOWN;
+       }
+}
+
+struct pipe_screen *r600_screen_create(struct radeon_winsys *ws)
+{
+       struct r600_screen *rscreen = CALLOC_STRUCT(r600_screen);
        if (rscreen == NULL) {
                return NULL;
        }
 
        rscreen->ws = ws;
-       rscreen->radeon = radeon;
+       ws->query_info(ws, &rscreen->info);
+
+       rscreen->family = radeon_family_from_device(rscreen->info.pci_id);
+       if (rscreen->family == CHIP_UNKNOWN) {
+               fprintf(stderr, "r600: Unknown chipset 0x%04X\n", rscreen->info.pci_id);
+               FREE(rscreen);
+               return NULL;
+       }
+
+       /* setup class */
+       if (rscreen->family == CHIP_CAYMAN) {
+               rscreen->chip_class = CAYMAN;
+       } else if (rscreen->family >= CHIP_CEDAR) {
+               rscreen->chip_class = EVERGREEN;
+       } else if (rscreen->family >= CHIP_RV770) {
+               rscreen->chip_class = R700;
+       } else {
+               rscreen->chip_class = R600;
+       }
+
+       if (r600_init_tiling(rscreen)) {
+               FREE(rscreen);
+               return NULL;
+       }
+
        rscreen->screen.winsys = (struct pipe_winsys*)ws;
        rscreen->screen.destroy = r600_destroy_screen;
        rscreen->screen.get_name = r600_get_name;
@@ -602,7 +781,7 @@ struct pipe_screen *r600_screen_create(struct radeon_winsys *ws)
        rscreen->screen.get_shader_param = r600_get_shader_param;
        rscreen->screen.get_paramf = r600_get_paramf;
        rscreen->screen.get_video_param = r600_get_video_param;
-       if (r600_get_family_class(radeon) >= EVERGREEN) {
+       if (rscreen->chip_class >= EVERGREEN) {
                rscreen->screen.is_format_supported = evergreen_is_format_supported;
        } else {
                rscreen->screen.is_format_supported = r600_is_format_supported;
@@ -614,11 +793,10 @@ struct pipe_screen *r600_screen_create(struct radeon_winsys *ws)
        rscreen->screen.fence_finish = r600_fence_finish;
        r600_init_screen_resource_functions(&rscreen->screen);
 
-       rscreen->tiling_info = r600_get_tiling_info(radeon);
        util_format_s3tc_init();
 
        util_slab_create(&rscreen->pool_buffers,
-                        sizeof(struct r600_resource_buffer), 64,
+                        sizeof(struct r600_resource), 64,
                         UTIL_SLAB_SINGLETHREADED);
 
        pipe_mutex_init(rscreen->mutex_num_contexts);