X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fgallium%2Fdrivers%2Fr600%2Fr600_pipe.c;h=140ae11af9a60ea7fbf0af4cb337791e8cd2665a;hb=f3f03c67e90f962f67e7b58b7c7baff3be251cb1;hp=16fe6c54a15380312fe693440b3954f4b15c4186;hpb=13c9a8552bc83b1ad91442caacf847cb6cead2b5;p=mesa.git diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 16fe6c54a15..140ae11af9a 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -22,54 +22,62 @@ */ #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#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 -#include -#include -#include -#include -#include +#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 "os/os_time.h" -#include +#include "pipebuffer/pb_buffer.h" #include "r600.h" #include "r600d.h" #include "r600_resource.h" #include "r600_shader.h" #include "r600_pipe.h" -#include "r600_state_inlines.h" /* * pipe_context */ -static struct r600_fence *r600_create_fence(struct r600_pipe_context *ctx) +static struct r600_fence *r600_create_fence(struct r600_context *rctx) { + struct r600_screen *rscreen = rctx->screen; struct r600_fence *fence = NULL; - if (!ctx->fences.bo) { + pipe_mutex_lock(rscreen->fences.mutex); + + if (!rscreen->fences.bo) { /* Create the shared buffer object */ - ctx->fences.bo = r600_bo(ctx->radeon, 4096, 0, 0, 0); - if (!ctx->fences.bo) { + rscreen->fences.bo = (struct r600_resource*) + pipe_buffer_create(&rscreen->screen, PIPE_BIND_CUSTOM, + PIPE_USAGE_STAGING, 4096); + if (!rscreen->fences.bo) { R600_ERR("r600: failed to create bo for fence objects\n"); - return NULL; + goto out; } - ctx->fences.data = r600_bo_map(ctx->radeon, ctx->fences.bo, PB_USAGE_UNSYNCHRONIZED, NULL); + rscreen->fences.data = rctx->ws->buffer_map(rscreen->fences.bo->buf, + rctx->cs, + PIPE_TRANSFER_READ_WRITE); } - if (!LIST_IS_EMPTY(&ctx->fences.pool)) { + if (!LIST_IS_EMPTY(&rscreen->fences.pool)) { struct r600_fence *entry; /* Try to find a freed fence that has been signalled */ - LIST_FOR_EACH_ENTRY(entry, &ctx->fences.pool, head) { - if (ctx->fences.data[entry->index] != 0) { + LIST_FOR_EACH_ENTRY(entry, &rscreen->fences.pool, head) { + if (rscreen->fences.data[entry->index] != 0) { LIST_DELINIT(&entry->head); fence = entry; break; @@ -82,62 +90,73 @@ static struct r600_fence *r600_create_fence(struct r600_pipe_context *ctx) struct r600_fence_block *block; unsigned index; - if ((ctx->fences.next_index + 1) >= 1024) { + if ((rscreen->fences.next_index + 1) >= 1024) { R600_ERR("r600: too many concurrent fences\n"); - return NULL; + goto out; } - index = ctx->fences.next_index++; + index = rscreen->fences.next_index++; if (!(index % FENCE_BLOCK_SIZE)) { /* Allocate a new block */ block = CALLOC_STRUCT(r600_fence_block); if (block == NULL) - return NULL; + goto out; - LIST_ADD(&block->head, &ctx->fences.blocks); + LIST_ADD(&block->head, &rscreen->fences.blocks); } else { - block = LIST_ENTRY(struct r600_fence_block, ctx->fences.blocks.next, head); + block = LIST_ENTRY(struct r600_fence_block, rscreen->fences.blocks.next, head); } fence = &block->fences[index % FENCE_BLOCK_SIZE]; - fence->ctx = ctx; fence->index = index; } pipe_reference_init(&fence->reference, 1); - ctx->fences.data[fence->index] = 0; - r600_context_emit_fence(&ctx->ctx, ctx->fences.bo, fence->index, 1); + rscreen->fences.data[fence->index] = 0; + r600_context_emit_fence(rctx, rscreen->fences.bo, fence->index, 1); +out: + pipe_mutex_unlock(rscreen->fences.mutex); return fence; } -static void r600_flush(struct pipe_context *ctx, - struct pipe_fence_handle **fence) + +void r600_flush(struct pipe_context *ctx, struct pipe_fence_handle **fence, + unsigned flags) { - struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; + struct r600_context *rctx = (struct r600_context *)ctx; struct r600_fence **rfence = (struct r600_fence**)fence; - -#if 0 - static int dc = 0; - char dname[256]; -#endif + struct pipe_query *render_cond = NULL; + unsigned render_cond_mode = 0; if (rfence) *rfence = r600_create_fence(rctx); - if (!rctx->ctx.pm4_cdwords) - return; + /* 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, flags); -#if 0 - sprintf(dname, "gallium-%08d.bof", dc); - if (dc < 20) { - r600_context_dump_bof(&rctx->ctx, dname); - R600_ERR("dumped %s\n", dname); + /* Re-enable render condition. */ + if (render_cond) { + ctx->render_condition(ctx, render_cond, render_cond_mode); } - dc++; -#endif - r600_context_flush(&rctx->ctx); +} + +static void r600_flush_from_st(struct pipe_context *ctx, + struct pipe_fence_handle **fence) +{ + r600_flush(ctx, fence, 0); +} + +static void r600_flush_from_winsys(void *ctx, unsigned flags) +{ + r600_flush((struct pipe_context*)ctx, NULL, flags); } static void r600_update_num_contexts(struct r600_screen *rscreen, int diff) @@ -161,12 +180,12 @@ static void r600_update_num_contexts(struct r600_screen *rscreen, int diff) static void r600_destroy_context(struct pipe_context *context) { - struct r600_pipe_context *rctx = (struct r600_pipe_context *)context; + struct r600_context *rctx = (struct r600_context *)context; rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush); util_unreference_framebuffer_state(&rctx->framebuffer); - r600_context_fini(&rctx->ctx); + r600_context_fini(rctx); util_blitter_destroy(rctx->blitter); @@ -174,21 +193,9 @@ 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) { - struct r600_fence_block *entry, *tmp; - - LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, &rctx->fences.blocks, head) { - LIST_DEL(&entry->head); - FREE(entry); - } - - r600_bo_unmap(rctx->radeon, rctx->fences.bo); - r600_bo_reference(rctx->radeon, &rctx->fences.bo, NULL); - } - r600_update_num_contexts(rctx->screen, -1); FREE(rctx); @@ -196,9 +203,8 @@ static void r600_destroy_context(struct pipe_context *context) static struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv) { - struct r600_pipe_context *rctx = CALLOC_STRUCT(r600_pipe_context); + struct r600_context *rctx = CALLOC_STRUCT(r600_context); struct r600_screen* rscreen = (struct r600_screen *)screen; - enum chip_class class; if (rctx == NULL) return NULL; @@ -209,18 +215,13 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void rctx->context.screen = screen; rctx->context.priv = priv; rctx->context.destroy = r600_destroy_context; - rctx->context.flush = r600_flush; + rctx->context.flush = r600_flush_from_st; /* Easy accessing of screen/winsys. */ rctx->screen = rscreen; - rctx->radeon = rscreen->radeon; - rctx->family = r600_get_family(rctx->radeon); - - rctx->fences.bo = NULL; - rctx->fences.data = NULL; - rctx->fences.next_index = 0; - LIST_INITHEAD(&rctx->fences.pool); - LIST_INITHEAD(&rctx->fences.blocks); + rctx->ws = rscreen->ws; + rctx->family = rscreen->family; + rctx->chip_class = rscreen->chip_class; r600_init_blit_functions(rctx); r600_init_query_functions(rctx); @@ -228,56 +229,45 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void r600_init_surface_functions(rctx); rctx->context.draw_vbo = r600_draw_vbo; - switch (r600_get_family(rctx->radeon)) { - case CHIP_R600: - case CHIP_RV610: - case CHIP_RV630: - case CHIP_RV670: - case CHIP_RV620: - case CHIP_RV635: - case CHIP_RS780: - case CHIP_RS880: - case CHIP_RV770: - case CHIP_RV730: - case CHIP_RV710: - case CHIP_RV740: + rctx->context.create_video_decoder = vl_create_decoder; + rctx->context.create_video_buffer = vl_video_buffer_create; + + r600_init_common_atoms(rctx); + + switch (rctx->chip_class) { + case R600: + case R700: r600_init_state_functions(rctx); - if (r600_context_init(&rctx->ctx, rctx->radeon)) { + if (r600_context_init(rctx)) { r600_destroy_context(&rctx->context); return NULL; } r600_init_config(rctx); + rctx->custom_dsa_flush = r600_create_db_flush_dsa(rctx); break; - case CHIP_CEDAR: - case CHIP_REDWOOD: - case CHIP_JUNIPER: - case CHIP_CYPRESS: - case CHIP_HEMLOCK: - case CHIP_PALM: - case CHIP_SUMO: - case CHIP_SUMO2: - case CHIP_BARTS: - case CHIP_TURKS: - case CHIP_CAICOS: - case CHIP_CAYMAN: + case EVERGREEN: + case CAYMAN: evergreen_init_state_functions(rctx); - if (evergreen_context_init(&rctx->ctx, rctx->radeon)) { + if (evergreen_context_init(rctx)) { r600_destroy_context(&rctx->context); return NULL; } evergreen_init_config(rctx); + rctx->custom_dsa_flush = evergreen_create_db_flush_dsa(rctx); break; default: - R600_ERR("unsupported family %d\n", r600_get_family(rctx->radeon)); + R600_ERR("Unsupported chip class %d.\n", rctx->chip_class); r600_destroy_context(&rctx->context); return NULL; } + rctx->ws->cs_set_flush_callback(rctx->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, @@ -286,6 +276,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void r600_destroy_context(&rctx->context); return NULL; } + rctx->vbuf_mgr->caps.format_fixed32 = 0; rctx->blitter = util_blitter_create(&rctx->context); if (rctx->blitter == NULL) { @@ -293,11 +284,9 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void return NULL; } - class = r600_get_family_class(rctx->radeon); - if (class == R600 || class == R700) - rctx->custom_dsa_flush = r600_create_db_flush_dsa(rctx); - else - rctx->custom_dsa_flush = evergreen_create_db_flush_dsa(rctx); + LIST_INITHEAD(&rctx->dirty_states); + + r600_get_backend_mask(rctx); /* this emits commands and must be last */ return &rctx->context; } @@ -344,40 +333,45 @@ 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: - case PIPE_CAP_DEPTH_CLAMP: + case PIPE_CAP_DEPTH_CLIP_DISABLE: case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: case PIPE_CAP_SM3: + case PIPE_CAP_SEAMLESS_CUBE_MAP: + case PIPE_CAP_PRIMITIVE_RESTART: + case PIPE_CAP_CONDITIONAL_RENDER: + case PIPE_CAP_TEXTURE_BARRIER: + case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: return 1; + case PIPE_CAP_GLSL_FEATURE_LEVEL: + return debug_get_bool_option("R600_GLSL130", FALSE) ? 130 : 120; + /* Supported except the original R600. */ case PIPE_CAP_INDEP_BLEND_ENABLE: case PIPE_CAP_INDEP_BLEND_FUNC: @@ -385,22 +379,28 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) return family == CHIP_R600 ? 0 : 1; /* Supported on Evergreen. */ - case PIPE_CAP_SEAMLESS_CUBE_MAP: case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: return family >= CHIP_CEDAR ? 1 : 0; /* Unsupported features. */ - case PIPE_CAP_STREAM_OUTPUT: - case PIPE_CAP_PRIMITIVE_RESTART: - case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL: 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: + case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: + case PIPE_CAP_VERTEX_COLOR_CLAMPED: 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_STREAM_OUTPUT_PAUSE_RESUME: + return debug_get_bool_option("R600_STREAMOUT", FALSE) ? 1 : 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: @@ -410,9 +410,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; @@ -423,36 +423,43 @@ 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) @@ -481,9 +488,9 @@ static int r600_get_shader_param(struct pipe_screen* pscreen, unsigned shader, e return 8; /* FIXME */ case PIPE_SHADER_CAP_MAX_INPUTS: if(shader == PIPE_SHADER_FRAGMENT) - return 10; + return 34; else - return 16; + return 32; case PIPE_SHADER_CAP_MAX_TEMPS: return 256; /* Max native temporaries. */ case PIPE_SHADER_CAP_MAX_ADDRS: @@ -492,7 +499,7 @@ static int r600_get_shader_param(struct pipe_screen* pscreen, unsigned shader, e case PIPE_SHADER_CAP_MAX_CONSTS: return R600_MAX_CONST_BUFFER_SIZE; case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: - return R600_MAX_CONST_BUFFERS; + return R600_MAX_CONST_BUFFERS-1; case PIPE_SHADER_CAP_MAX_PREDS: return 0; /* FIXME */ case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: @@ -504,67 +511,39 @@ static int r600_get_shader_param(struct pipe_screen* pscreen, unsigned shader, e return 1; case PIPE_SHADER_CAP_SUBROUTINES: return 0; - default: + case PIPE_SHADER_CAP_INTEGERS: return 0; + case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: + return 16; + case PIPE_SHADER_CAP_OUTPUT_READ: + return 1; } + return 0; } -static boolean r600_is_format_supported(struct pipe_screen* screen, - enum pipe_format format, - enum pipe_texture_target target, - unsigned sample_count, - unsigned usage) +static int r600_get_video_param(struct pipe_screen *screen, + enum pipe_video_profile profile, + enum pipe_video_cap param) { - unsigned retval = 0; - if (target >= PIPE_MAX_TEXTURE_TYPES) { - R600_ERR("r600: unsupported texture type %d\n", target); - return FALSE; - } - - if (!util_format_is_supported(format, usage)) - return FALSE; - - /* Multisample */ - if (sample_count > 1) - return FALSE; - - if ((usage & PIPE_BIND_SAMPLER_VIEW) && - r600_is_sampler_format_supported(screen, format)) { - retval |= PIPE_BIND_SAMPLER_VIEW; - } - - if ((usage & (PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_SCANOUT | - PIPE_BIND_SHARED)) && - r600_is_colorbuffer_format_supported(format)) { - retval |= usage & - (PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_SCANOUT | - PIPE_BIND_SHARED); - } - - if ((usage & PIPE_BIND_DEPTH_STENCIL) && - r600_is_zs_format_supported(format)) { - retval |= PIPE_BIND_DEPTH_STENCIL; - } - - if (usage & PIPE_BIND_VERTEX_BUFFER) { - struct r600_screen *rscreen = (struct r600_screen *)screen; - enum radeon_family family = r600_get_family(rscreen->radeon); - - if (r600_is_vertex_format_supported(format, family)) { - retval |= PIPE_BIND_VERTEX_BUFFER; - } + switch (param) { + case PIPE_VIDEO_CAP_SUPPORTED: + return vl_profile_supported(screen, profile); + case PIPE_VIDEO_CAP_NPOT_TEXTURES: + return 1; + case PIPE_VIDEO_CAP_MAX_WIDTH: + case PIPE_VIDEO_CAP_MAX_HEIGHT: + return vl_video_buffer_max_size(screen); + case PIPE_VIDEO_CAP_PREFERED_FORMAT: + return PIPE_FORMAT_NV12; + case PIPE_VIDEO_CAP_PREFERS_INTERLACED: + return false; + case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: + return false; + case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: + return true; + default: + return 0; } - - if (usage & PIPE_BIND_TRANSFER_READ) - retval |= PIPE_BIND_TRANSFER_READ; - if (usage & PIPE_BIND_TRANSFER_WRITE) - retval |= PIPE_BIND_TRANSFER_WRITE; - - return retval == usage; } static void r600_destroy_screen(struct pipe_screen* pscreen) @@ -574,7 +553,20 @@ static void r600_destroy_screen(struct pipe_screen* pscreen) if (rscreen == NULL) return; - radeon_decref(rscreen->radeon); + if (rscreen->fences.bo) { + struct r600_fence_block *entry, *tmp; + + LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, &rscreen->fences.blocks, head) { + LIST_DEL(&entry->head); + FREE(entry); + } + + rscreen->ws->buffer_unmap(rscreen->fences.bo->buf); + pipe_resource_reference((struct pipe_resource**)&rscreen->fences.bo, NULL); + } + pipe_mutex_destroy(rscreen->fences.mutex); + + rscreen->ws->destroy(rscreen->ws); util_slab_destroy(&rscreen->pool_buffers); pipe_mutex_destroy(rscreen->mutex_num_contexts); @@ -589,8 +581,10 @@ static void r600_fence_reference(struct pipe_screen *pscreen, struct r600_fence *newf = (struct r600_fence*)fence; if (pipe_reference(&(*oldf)->reference, &newf->reference)) { - struct r600_pipe_context *ctx = (*oldf)->ctx; - LIST_ADDTAIL(&(*oldf)->head, &ctx->fences.pool); + struct r600_screen *rscreen = (struct r600_screen *)pscreen; + pipe_mutex_lock(rscreen->fences.mutex); + LIST_ADDTAIL(&(*oldf)->head, &rscreen->fences.pool); + pipe_mutex_unlock(rscreen->fences.mutex); } *ptr = fence; @@ -599,18 +593,18 @@ static void r600_fence_reference(struct pipe_screen *pscreen, static boolean r600_fence_signalled(struct pipe_screen *pscreen, struct pipe_fence_handle *fence) { + struct r600_screen *rscreen = (struct r600_screen *)pscreen; struct r600_fence *rfence = (struct r600_fence*)fence; - struct r600_pipe_context *ctx = rfence->ctx; - return ctx->fences.data[rfence->index]; + return rscreen->fences.data[rfence->index]; } static boolean r600_fence_finish(struct pipe_screen *pscreen, struct pipe_fence_handle *fence, uint64_t timeout) { + struct r600_screen *rscreen = (struct r600_screen *)pscreen; struct r600_fence *rfence = (struct r600_fence*)fence; - struct r600_pipe_context *ctx = rfence->ctx; int64_t start_time = 0; unsigned spins = 0; @@ -621,7 +615,7 @@ static boolean r600_fence_finish(struct pipe_screen *pscreen, timeout /= 1000; } - while (ctx->fences.data[rfence->index] == 0) { + while (rscreen->fences.data[rfence->index] == 0) { if (++spins % 256) continue; #ifdef PIPE_OS_UNIX @@ -638,38 +632,194 @@ static boolean r600_fence_finish(struct pipe_screen *pscreen, return TRUE; } -struct pipe_screen *r600_screen_create(struct radeon *radeon) +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; + 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; + } + + if (!tiling_config) + return 0; - rscreen = CALLOC_STRUCT(r600_screen); + 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->radeon = radeon; - rscreen->screen.winsys = (struct pipe_winsys*)radeon; + rscreen->ws = ws; + 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; rscreen->screen.get_vendor = r600_get_vendor; rscreen->screen.get_param = r600_get_param; rscreen->screen.get_shader_param = r600_get_shader_param; rscreen->screen.get_paramf = r600_get_paramf; - rscreen->screen.is_format_supported = r600_is_format_supported; + rscreen->screen.get_video_param = r600_get_video_param; + if (rscreen->chip_class >= EVERGREEN) { + rscreen->screen.is_format_supported = evergreen_is_format_supported; + } else { + rscreen->screen.is_format_supported = r600_is_format_supported; + } + rscreen->screen.is_video_format_supported = vl_video_buffer_is_format_supported; rscreen->screen.context_create = r600_create_context; rscreen->screen.fence_reference = r600_fence_reference; rscreen->screen.fence_signalled = r600_fence_signalled; 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); + rscreen->fences.bo = NULL; + rscreen->fences.data = NULL; + rscreen->fences.next_index = 0; + LIST_INITHEAD(&rscreen->fences.pool); + LIST_INITHEAD(&rscreen->fences.blocks); + pipe_mutex_init(rscreen->fences.mutex); + return &rscreen->screen; }