diff options
Diffstat (limited to 'src/gallium/winsys')
40 files changed, 2241 insertions, 1809 deletions
diff --git a/src/gallium/winsys/SConscript b/src/gallium/winsys/SConscript index d74f8a2e98..9f36d225e1 100644 --- a/src/gallium/winsys/SConscript +++ b/src/gallium/winsys/SConscript @@ -13,6 +13,10 @@ SConscript([ 'sw/gdi/SConscript', ]) +SConscript([ + 'i915/sw/SConscript', +]) + if env['dri']: SConscript([ 'sw/dri/SConscript', diff --git a/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c b/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c index ebe86dcf19..03aa1b1537 100644 --- a/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c +++ b/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c @@ -4,6 +4,8 @@ #include "i915_drm.h" #include "i915/i915_debug.h" +#include <xf86drm.h> +#include <stdio.h> #define BATCH_RESERVED 16 @@ -34,7 +36,6 @@ static void i915_drm_batchbuffer_reset(struct i915_drm_batchbuffer *batch) { struct i915_drm_winsys *idws = i915_drm_winsys(batch->base.iws); - int ret; if (batch->bo) drm_intel_bo_unreference(batch->bo); @@ -43,18 +44,6 @@ i915_drm_batchbuffer_reset(struct i915_drm_batchbuffer *batch) batch->actual_size, 4096); -#ifdef INTEL_MAP_BATCHBUFFER -#ifdef INTEL_MAP_GTT - ret = drm_intel_gem_bo_map_gtt(batch->bo); -#else - ret = drm_intel_bo_map(batch->bo, TRUE); -#endif - assert(ret == 0); - batch->base.map = batch->bo->virtual; -#else - (void)ret; -#endif - memset(batch->base.map, 0, batch->actual_size); batch->base.ptr = batch->base.map; batch->base.size = batch->actual_size - BATCH_RESERVED; @@ -74,7 +63,6 @@ i915_drm_batchbuffer_create(struct i915_winsys *iws) batch->base.size = 0; batch->base.relocs = 0; - batch->base.max_relocs = 300;/*INTEL_DEFAULT_RELOCS;*/ batch->base.iws = iws; @@ -83,11 +71,31 @@ i915_drm_batchbuffer_create(struct i915_winsys *iws) return &batch->base; } +static boolean +i915_drm_batchbuffer_validate_buffers(struct i915_winsys_batchbuffer *batch, + struct i915_winsys_buffer **buffer, + int num_of_buffers) +{ + struct i915_drm_batchbuffer *drm_batch = i915_drm_batchbuffer(batch); + drm_intel_bo *bos[num_of_buffers + 1]; + int i, ret; + + bos[0] = drm_batch->bo; + for (i = 0; i < num_of_buffers; i++) + bos[i+1] = intel_bo(buffer[i]); + + ret = drm_intel_bufmgr_check_aperture_space(bos, num_of_buffers); + if (ret != 0) + return FALSE; + + return TRUE; +} + static int i915_drm_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch, struct i915_winsys_buffer *buffer, enum i915_winsys_buffer_usage usage, - unsigned pre_add, bool fenced) + unsigned pre_add, boolean fenced) { struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch); unsigned write_domain = 0; @@ -95,8 +103,6 @@ i915_drm_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch, unsigned offset; int ret = 0; - assert(batch->base.relocs < batch->base.max_relocs); - switch (usage) { case I915_USAGE_SAMPLER: write_domain = 0; @@ -145,6 +151,12 @@ i915_drm_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch, return ret; } +static void +i915_drm_throttle(struct i915_drm_winsys *idws) +{ + drmIoctl(idws->fd, DRM_IOCTL_I915_GEM_THROTTLE, NULL); +} + static void i915_drm_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch, struct pipe_fence_handle **fence) @@ -168,11 +180,21 @@ i915_drm_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch, if (ret == 0 && i915_drm_winsys(ibatch->iws)->send_cmd) ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0); + i915_drm_throttle(i915_drm_winsys(ibatch->iws)); + if (ret != 0 || i915_drm_winsys(ibatch->iws)->dump_cmd) { i915_dump_batchbuffer(ibatch); assert(ret == 0); } + if (i915_drm_winsys(ibatch->iws)->dump_raw_file) { + FILE *file = fopen(i915_drm_winsys(ibatch->iws)->dump_raw_file, "a"); + if (file) { + fwrite(batch->base.map, used, 1, file); + fclose(file); + } + } + #ifdef INTEL_RUN_SYNC drm_intel_bo_wait_rendering(batch->bo); #endif @@ -206,6 +228,7 @@ i915_drm_batchbuffer_destroy(struct i915_winsys_batchbuffer *ibatch) void i915_drm_winsys_init_batchbuffer_functions(struct i915_drm_winsys *idws) { idws->base.batchbuffer_create = i915_drm_batchbuffer_create; + idws->base.validate_buffers = i915_drm_batchbuffer_validate_buffers; idws->base.batchbuffer_reloc = i915_drm_batchbuffer_reloc; idws->base.batchbuffer_flush = i915_drm_batchbuffer_flush; idws->base.batchbuffer_destroy = i915_drm_batchbuffer_destroy; diff --git a/src/gallium/winsys/i915/drm/i915_drm_winsys.c b/src/gallium/winsys/i915/drm/i915_drm_winsys.c index 2288b48b2b..2c3b508d05 100644 --- a/src/gallium/winsys/i915/drm/i915_drm_winsys.c +++ b/src/gallium/winsys/i915/drm/i915_drm_winsys.c @@ -72,6 +72,7 @@ i915_drm_winsys_create(int drmFD) drm_intel_bufmgr_gem_enable_fenced_relocs(idws->gem_manager); idws->dump_cmd = debug_get_bool_option("I915_DUMP_CMD", FALSE); + idws->dump_raw_file = debug_get_option("I915_DUMP_RAW_FILE", NULL); idws->send_cmd = !debug_get_bool_option("I915_NO_HW", FALSE); return &idws->base; diff --git a/src/gallium/winsys/i915/drm/i915_drm_winsys.h b/src/gallium/winsys/i915/drm/i915_drm_winsys.h index 0d74d0270c..dae53c3e80 100644 --- a/src/gallium/winsys/i915/drm/i915_drm_winsys.h +++ b/src/gallium/winsys/i915/drm/i915_drm_winsys.h @@ -18,6 +18,7 @@ struct i915_drm_winsys struct i915_winsys base; boolean dump_cmd; + char *dump_raw_file; boolean send_cmd; int fd; /**< Drm file discriptor */ diff --git a/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c b/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c index 44773ae30e..3bf54011d9 100644 --- a/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c +++ b/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c @@ -1,6 +1,7 @@ #include "i915_sw_winsys.h" #include "i915/i915_batchbuffer.h" +#include "i915/i915_debug.h" #include "util/u_memory.h" #define BATCH_RESERVED 16 @@ -48,7 +49,6 @@ i915_sw_batchbuffer_create(struct i915_winsys *iws) batch->base.size = 0; batch->base.relocs = 0; - batch->base.max_relocs = 300;/*INTEL_DEFAULT_RELOCS;*/ batch->base.iws = iws; @@ -57,17 +57,23 @@ i915_sw_batchbuffer_create(struct i915_winsys *iws) return &batch->base; } +static boolean +i915_sw_batchbuffer_validate_buffers(struct i915_winsys_batchbuffer *batch, + struct i915_winsys_buffer **buffer, + int num_of_buffers) +{ + return TRUE; +} + static int i915_sw_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch, struct i915_winsys_buffer *buffer, enum i915_winsys_buffer_usage usage, - unsigned pre_add, bool fenced) + unsigned pre_add, boolean fenced) { struct i915_sw_batchbuffer *batch = i915_sw_batchbuffer(ibatch); int ret = 0; - assert(batch->base.relocs < batch->base.max_relocs); - if (usage == I915_USAGE_SAMPLER) { } else if (usage == I915_USAGE_RENDER) { @@ -98,7 +104,6 @@ i915_sw_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch, { struct i915_sw_batchbuffer *batch = i915_sw_batchbuffer(ibatch); unsigned used = 0; - int i; assert(i915_winsys_batchbuffer_space(ibatch) >= 0); @@ -107,27 +112,22 @@ i915_sw_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch, #ifdef INTEL_ALWAYS_FLUSH /* MI_FLUSH | FLUSH_MAP_CACHE */ - i915_winsys_batchbuffer_dword(ibatch, (0x4<<23)|(1<<0)); + i915_winsys_batchbuffer_dword_unchecked(ibatch, (0x4<<23)|(1<<0)); used += 4; #endif if ((used & 4) == 0) { /* MI_NOOP */ - i915_winsys_batchbuffer_dword(ibatch, 0); + i915_winsys_batchbuffer_dword_unchecked(ibatch, 0); } /* MI_BATCH_BUFFER_END */ - i915_winsys_batchbuffer_dword(ibatch, (0xA<<23)); + i915_winsys_batchbuffer_dword_unchecked(ibatch, (0xA<<23)); used = batch->base.ptr - batch->base.map; assert((used & 4) == 0); if (i915_sw_winsys(ibatch->iws)->dump_cmd) { - unsigned *ptr = (unsigned *)batch->base.map; - - debug_printf("%s:\n", __func__); - for (i = 0; i < used / 4; i++, ptr++) { - debug_printf("\t%08x: %08x\n", i*4, *ptr); - } + i915_dump_batchbuffer(ibatch); } if (fence) { @@ -151,6 +151,7 @@ i915_sw_batchbuffer_destroy(struct i915_winsys_batchbuffer *ibatch) void i915_sw_winsys_init_batchbuffer_functions(struct i915_sw_winsys *isws) { isws->base.batchbuffer_create = i915_sw_batchbuffer_create; + isws->base.validate_buffers = i915_sw_batchbuffer_validate_buffers; isws->base.batchbuffer_reloc = i915_sw_batchbuffer_reloc; isws->base.batchbuffer_flush = i915_sw_batchbuffer_flush; isws->base.batchbuffer_destroy = i915_sw_batchbuffer_destroy; diff --git a/src/gallium/winsys/i915/sw/i915_sw_buffer.c b/src/gallium/winsys/i915/sw/i915_sw_buffer.c index 834805e621..9a7e90e217 100644 --- a/src/gallium/winsys/i915/sw/i915_sw_buffer.c +++ b/src/gallium/winsys/i915/sw/i915_sw_buffer.c @@ -84,7 +84,7 @@ i915_sw_buffer_write(struct i915_winsys *iws, { struct i915_sw_buffer *buf = i915_sw_buffer(buffer); - memcpy(buf->ptr + offset, data, size); + memcpy((char*)buf->ptr + offset, data, size); return 0; } diff --git a/src/gallium/winsys/i915/sw/i915_sw_winsys.c b/src/gallium/winsys/i915/sw/i915_sw_winsys.c index 058ddc44aa..fc48da6fb9 100644 --- a/src/gallium/winsys/i915/sw/i915_sw_winsys.c +++ b/src/gallium/winsys/i915/sw/i915_sw_winsys.c @@ -50,7 +50,7 @@ i915_sw_winsys_create() isws->base.pci_id = deviceID; isws->max_batch_size = 16 * 4096; - isws->dump_cmd = debug_get_bool_option("INTEL_DUMP_CMD", FALSE); + isws->dump_cmd = debug_get_bool_option("I915_DUMP_CMD", FALSE); return &isws->base; } diff --git a/src/gallium/winsys/i965/drm/i965_drm_buffer.c b/src/gallium/winsys/i965/drm/i965_drm_buffer.c index ed62db60bb..a904179eeb 100644 --- a/src/gallium/winsys/i965/drm/i965_drm_buffer.c +++ b/src/gallium/winsys/i965/drm/i965_drm_buffer.c @@ -325,7 +325,7 @@ i965_libdrm_bo_subdata(struct brw_winsys_buffer *buffer, brw_dump_data( idws->base.pci_id, data_type, buf->bo->offset + offset, - data, size ); + data, size, buffer->sws->gen ); /* XXX: use bo_map_gtt/memcpy/unmap_gtt under some circumstances??? */ @@ -464,7 +464,7 @@ i965_libdrm_bo_flush_range(struct brw_winsys_buffer *buffer, buf->data_type, buf->bo->offset + offset, (char*)buf->bo->virtual + offset, - length ); + length, buffer->sws->gen ); } static void diff --git a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c index d4bf124ce6..648d6c8a8e 100644 --- a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c +++ b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c @@ -50,6 +50,9 @@ nouveau_drm_screen_create(int fd) case 0xa0: init = nv50_screen_create; break; + case 0xc0: + init = nvc0_screen_create; + break; default: debug_printf("%s: unknown chipset nv%02x\n", __func__, dev->chipset); diff --git a/src/gallium/winsys/r600/Android.mk b/src/gallium/winsys/r600/Android.mk new file mode 100644 index 0000000000..643a59dc42 --- /dev/null +++ b/src/gallium/winsys/r600/Android.mk @@ -0,0 +1,38 @@ +ifeq ($(strip $(MESA_BUILD_R600G)),true) + +LOCAL_PATH := $(call my-dir) + +# from drm/Makefile +C_SOURCES = \ + bof.c \ + evergreen_hw_context.c \ + radeon_bo.c \ + radeon_pciid.c \ + r600_bo.c \ + r600_drm.c \ + r600_hw_context.c \ + r600_bomgr.c + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + $(addprefix drm/, $(C_SOURCES)) + +LOCAL_CFLAGS := \ + -std=c99 \ + -fvisibility=hidden \ + -Wno-sign-compare + +LOCAL_C_INCLUDES := \ + external/mesa/include \ + external/mesa/src/gallium/include \ + external/mesa/src/gallium/auxiliary \ + external/mesa/src/gallium/drivers/r600 \ + external/drm \ + external/drm/include/drm + +LOCAL_MODULE := libmesa_winsys_r600 + +include $(BUILD_STATIC_LIBRARY) + +endif # MESA_BUILD_R600G diff --git a/src/gallium/winsys/r600/drm/Makefile b/src/gallium/winsys/r600/drm/Makefile index a396205f89..7310734f05 100644 --- a/src/gallium/winsys/r600/drm/Makefile +++ b/src/gallium/winsys/r600/drm/Makefile @@ -8,12 +8,11 @@ C_SOURCES = \ bof.c \ evergreen_hw_context.c \ radeon_bo.c \ - radeon_bo_pb.c \ radeon_pciid.c \ - r600.c \ r600_bo.c \ r600_drm.c \ - r600_hw_context.c + r600_hw_context.c \ + r600_bomgr.c LIBRARY_INCLUDES = -I$(TOP)/src/gallium/drivers/r600 \ $(shell pkg-config libdrm --cflags-only-I) diff --git a/src/gallium/winsys/r600/drm/SConscript b/src/gallium/winsys/r600/drm/SConscript index cc053c06dd..cc9a06a239 100644 --- a/src/gallium/winsys/r600/drm/SConscript +++ b/src/gallium/winsys/r600/drm/SConscript @@ -6,15 +6,19 @@ r600_sources = [ 'bof.c', 'evergreen_hw_context.c', 'radeon_bo.c', - 'radeon_bo_pb.c', 'radeon_pciid.c', - 'r600.c', 'r600_bo.c', 'r600_drm.c', 'r600_hw_context.c', + 'r600_bomgr.c', ] -env.ParseConfig('pkg-config --cflags libdrm_radeon') +try: + env.ParseConfig('pkg-config --cflags libdrm_radeon') +except OSError: + print 'warning: not building r600g' + Return() + env.Append(CPPPATH = '#/src/gallium/drivers/r600') r600winsys = env.ConvenienceLibrary( diff --git a/src/gallium/winsys/r600/drm/bof.c b/src/gallium/winsys/r600/drm/bof.c index 0598cc6bc0..5c923ad38d 100644 --- a/src/gallium/winsys/r600/drm/bof.c +++ b/src/gallium/winsys/r600/drm/bof.c @@ -46,7 +46,7 @@ static int bof_entry_grow(bof_t *bof) } /* - * object + * object */ bof_t *bof_object(void) { diff --git a/src/gallium/winsys/r600/drm/evergreen_hw_context.c b/src/gallium/winsys/r600/drm/evergreen_hw_context.c index e1f163eab6..66398afa69 100644 --- a/src/gallium/winsys/r600/drm/evergreen_hw_context.c +++ b/src/gallium/winsys/r600/drm/evergreen_hw_context.c @@ -36,7 +36,6 @@ #include "pipe/p_compiler.h" #include "util/u_inlines.h" #include "util/u_memory.h" -#include <pipebuffer/pb_bufmgr.h> #include "r600_priv.h" #define GROUP_FORCE_NEW_BLOCK 0 @@ -622,10 +621,9 @@ int evergreen_context_init(struct r600_context *ctx, struct radeon *radeon) /* save 16dwords space for fence mecanism */ ctx->pm4_ndwords -= 16; - r = r600_context_init_fence(ctx); - if (r) { - goto out_err; - } + ctx->max_db = 8; + + LIST_INITHEAD(&ctx->fenced_bo); /* init dirty list */ LIST_INITHEAD(&ctx->dirty); @@ -836,25 +834,25 @@ void evergreen_context_draw(struct r600_context *ctx, const struct r600_draw *dr } /* draw packet */ - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_INDEX_TYPE, 0); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_INDEX_TYPE, 0, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_index_type; - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NUM_INSTANCES, 0); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NUM_INSTANCES, 0, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_num_instances; if (draw->indices) { - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_DRAW_INDEX, 3); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_DRAW_INDEX, 3, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = draw->indices_bo_offset + r600_bo_offset(draw->indices); ctx->pm4[ctx->pm4_cdwords++] = 0; ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_num_indices; ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_draw_initiator; - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = 0; r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], draw->indices); } else { - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_DRAW_INDEX_AUTO, 1); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_DRAW_INDEX_AUTO, 1, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_num_indices; ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_draw_initiator; } - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 0); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 0, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0); /* flush color buffer */ @@ -881,59 +879,3 @@ void evergreen_context_draw(struct r600_context *ctx, const struct r600_draw *dr ctx->pm4_dirty_cdwords = 0; } -static inline void evergreen_resource_set(struct r600_context *ctx, struct r600_pipe_state *state, unsigned offset) -{ - struct r600_range *range; - struct r600_block *block; - - range = &ctx->range[CTX_RANGE_ID(ctx, offset)]; - block = range->blocks[CTX_BLOCK_ID(ctx, offset)]; - block->reg[0] = state->regs[0].value; - block->reg[1] = state->regs[1].value; - block->reg[2] = state->regs[2].value; - block->reg[3] = state->regs[3].value; - block->reg[4] = state->regs[4].value; - block->reg[5] = state->regs[5].value; - block->reg[6] = state->regs[6].value; - block->reg[7] = state->regs[7].value; - r600_bo_reference(ctx->radeon, &block->reloc[1].bo, NULL); - r600_bo_reference(ctx->radeon , &block->reloc[2].bo, NULL); - if (state->regs[0].bo) { - /* VERTEX RESOURCE, we preted there is 2 bo to relocate so - * we have single case btw VERTEX & TEXTURE resource - */ - r600_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[0].bo); - r600_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[0].bo); - } else { - /* TEXTURE RESOURCE */ - r600_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[2].bo); - r600_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[3].bo); - } - if (!(block->status & R600_BLOCK_STATUS_DIRTY)) { - block->status |= R600_BLOCK_STATUS_ENABLED; - block->status |= R600_BLOCK_STATUS_DIRTY; - ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords; - LIST_ADDTAIL(&block->list,&ctx->dirty); - } -} - -void evergreen_ps_resource_set(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid) -{ - unsigned offset = R_030000_RESOURCE0_WORD0 + 0x20 * rid; - - evergreen_resource_set(ctx, state, offset); -} - -void evergreen_vs_resource_set(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid) -{ - unsigned offset = R_030000_RESOURCE0_WORD0 + 0x1600 + 0x20 * rid; - - evergreen_resource_set(ctx, state, offset); -} - -void evergreen_fs_resource_set(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid) -{ - unsigned offset = R_030000_RESOURCE0_WORD0 + 0x7C00 + 0x20 * rid; - - evergreen_resource_set(ctx, state, offset); -} diff --git a/src/gallium/winsys/r600/drm/r600.c b/src/gallium/winsys/r600/drm/r600.c deleted file mode 100644 index f5e53e21f5..0000000000 --- a/src/gallium/winsys/r600/drm/r600.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2010 Jerome Glisse <glisse@freedesktop.org> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Jerome Glisse - */ -#include "xf86drm.h" -#include "radeon_drm.h" -#include "pipe/p_compiler.h" -#include "util/u_inlines.h" -#include <pipebuffer/pb_bufmgr.h> -#include "r600_priv.h" - -enum radeon_family r600_get_family(struct radeon *r600) -{ - return r600->family; -} - -enum chip_class r600_get_family_class(struct radeon *radeon) -{ - return radeon->chip_class; -} - -struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon) -{ - return &radeon->tiling_info; -} - -static int r600_get_device(struct radeon *r600) -{ - struct drm_radeon_info info; - - r600->device = 0; - info.request = RADEON_INFO_DEVICE_ID; - info.value = (uintptr_t)&r600->device; - return drmCommandWriteRead(r600->fd, DRM_RADEON_INFO, &info, sizeof(struct drm_radeon_info)); -} - -struct radeon *r600_new(int fd, unsigned device) -{ - struct radeon *r600; - int r; - - r600 = calloc(1, sizeof(*r600)); - if (r600 == NULL) { - return NULL; - } - r600->fd = fd; - r600->device = device; - if (fd >= 0) { - r = r600_get_device(r600); - if (r) { - R600_ERR("Failed to get device id\n"); - r600_delete(r600); - return NULL; - } - } - r600->family = radeon_family_from_device(r600->device); - if (r600->family == CHIP_UNKNOWN) { - R600_ERR("Unknown chipset 0x%04X\n", r600->device); - r600_delete(r600); - return NULL; - } - switch (r600->family) { - 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: - case CHIP_CEDAR: - case CHIP_REDWOOD: - case CHIP_JUNIPER: - case CHIP_CYPRESS: - case CHIP_HEMLOCK: - case CHIP_PALM: - break; - case CHIP_R100: - case CHIP_RV100: - case CHIP_RS100: - case CHIP_RV200: - case CHIP_RS200: - case CHIP_R200: - case CHIP_RV250: - case CHIP_RS300: - case CHIP_RV280: - case CHIP_R300: - case CHIP_R350: - case CHIP_RV350: - case CHIP_RV380: - case CHIP_R420: - case CHIP_R423: - case CHIP_RV410: - case CHIP_RS400: - case CHIP_RS480: - case CHIP_RS600: - case CHIP_RS690: - case CHIP_RS740: - case CHIP_RV515: - case CHIP_R520: - case CHIP_RV530: - case CHIP_RV560: - case CHIP_RV570: - case CHIP_R580: - default: - R600_ERR("unknown or unsupported chipset 0x%04X\n", r600->device); - break; - } - - /* setup class */ - switch (r600->family) { - case CHIP_R600: - case CHIP_RV610: - case CHIP_RV630: - case CHIP_RV670: - case CHIP_RV620: - case CHIP_RV635: - case CHIP_RS780: - case CHIP_RS880: - r600->chip_class = R600; - break; - case CHIP_RV770: - case CHIP_RV730: - case CHIP_RV710: - case CHIP_RV740: - r600->chip_class = R700; - break; - case CHIP_CEDAR: - case CHIP_REDWOOD: - case CHIP_JUNIPER: - case CHIP_CYPRESS: - case CHIP_HEMLOCK: - case CHIP_PALM: - r600->chip_class = EVERGREEN; - break; - default: - R600_ERR("unknown or unsupported chipset 0x%04X\n", r600->device); - break; - } - - return r600; -} - -void r600_delete(struct radeon *r600) -{ - if (r600 == NULL) - return; - drmClose(r600->fd); - free(r600); -} diff --git a/src/gallium/winsys/r600/drm/r600_bo.c b/src/gallium/winsys/r600/drm/r600_bo.c index 251f009a6b..122a68884b 100644 --- a/src/gallium/winsys/r600/drm/r600_bo.c +++ b/src/gallium/winsys/r600/drm/r600_bo.c @@ -36,142 +36,152 @@ struct r600_bo *r600_bo(struct radeon *radeon, unsigned size, unsigned alignment, unsigned binding, unsigned usage) { - struct r600_bo *ws_bo = calloc(1, sizeof(struct r600_bo)); - struct pb_desc desc; - struct pb_manager *man; + struct r600_bo *bo; + struct radeon_bo *rbo; - desc.alignment = alignment; - desc.usage = (PB_USAGE_CPU_READ_WRITE | PB_USAGE_GPU_READ_WRITE); - ws_bo->size = size; + if (binding & (PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) { + bo = r600_bomgr_bo_create(radeon->bomgr, size, alignment, *radeon->cfence); + if (bo) { + return bo; + } + } - if (binding & (PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) - man = radeon->cman; - else - man = radeon->kman; + rbo = radeon_bo(radeon, 0, size, alignment); + if (rbo == NULL) { + return NULL; + } + + bo = calloc(1, sizeof(struct r600_bo)); + bo->size = size; + bo->alignment = alignment; + bo->bo = rbo; + if (binding & (PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) { + r600_bomgr_bo_init(radeon->bomgr, bo); + } /* Staging resources particpate in transfers and blits only * and are used for uploads and downloads from regular * resources. We generate them internally for some transfers. */ if (usage == PIPE_USAGE_STAGING) - ws_bo->domains = RADEON_GEM_DOMAIN_CPU | RADEON_GEM_DOMAIN_GTT; - else - ws_bo->domains = (RADEON_GEM_DOMAIN_CPU | - RADEON_GEM_DOMAIN_GTT | - RADEON_GEM_DOMAIN_VRAM); - - - ws_bo->pb = man->create_buffer(man, size, &desc); - if (ws_bo->pb == NULL) { - free(ws_bo); - return NULL; - } + bo->domains = RADEON_GEM_DOMAIN_CPU | RADEON_GEM_DOMAIN_GTT; + else + bo->domains = (RADEON_GEM_DOMAIN_CPU | + RADEON_GEM_DOMAIN_GTT | + RADEON_GEM_DOMAIN_VRAM); - pipe_reference_init(&ws_bo->reference, 1); - return ws_bo; + pipe_reference_init(&bo->reference, 1); + return bo; } struct r600_bo *r600_bo_handle(struct radeon *radeon, unsigned handle, unsigned *array_mode) { - struct r600_bo *ws_bo = calloc(1, sizeof(struct r600_bo)); - struct radeon_bo *bo; + struct r600_bo *bo = calloc(1, sizeof(struct r600_bo)); + struct radeon_bo *rbo; - ws_bo->pb = radeon_bo_pb_create_buffer_from_handle(radeon->kman, handle); - if (!ws_bo->pb) { - free(ws_bo); + rbo = bo->bo = radeon_bo(radeon, handle, 0, 0); + if (rbo == NULL) { + free(bo); return NULL; } - bo = radeon_bo_pb_get_bo(ws_bo->pb); - ws_bo->size = bo->size; - ws_bo->domains = (RADEON_GEM_DOMAIN_CPU | - RADEON_GEM_DOMAIN_GTT | - RADEON_GEM_DOMAIN_VRAM); + bo->size = rbo->size; + bo->domains = (RADEON_GEM_DOMAIN_CPU | + RADEON_GEM_DOMAIN_GTT | + RADEON_GEM_DOMAIN_VRAM); - pipe_reference_init(&ws_bo->reference, 1); + pipe_reference_init(&bo->reference, 1); - radeon_bo_get_tiling_flags(radeon, bo, &ws_bo->tiling_flags, - &ws_bo->kernel_pitch); + radeon_bo_get_tiling_flags(radeon, rbo, &bo->tiling_flags, &bo->kernel_pitch); if (array_mode) { - if (ws_bo->tiling_flags) { - if (ws_bo->tiling_flags & RADEON_TILING_MICRO) - *array_mode = V_0280A0_ARRAY_1D_TILED_THIN1; - if ((ws_bo->tiling_flags & (RADEON_TILING_MICRO | RADEON_TILING_MACRO)) == - (RADEON_TILING_MICRO | RADEON_TILING_MACRO)) + if (bo->tiling_flags) { + if (bo->tiling_flags & RADEON_TILING_MACRO) *array_mode = V_0280A0_ARRAY_2D_TILED_THIN1; + else if (bo->tiling_flags & RADEON_TILING_MICRO) + *array_mode = V_0280A0_ARRAY_1D_TILED_THIN1; } else { *array_mode = 0; } } - return ws_bo; + return bo; } void *r600_bo_map(struct radeon *radeon, struct r600_bo *bo, unsigned usage, void *ctx) { - return pb_map(bo->pb, usage, ctx); + struct pipe_context *pctx = ctx; + + if (usage & PB_USAGE_UNSYNCHRONIZED) { + radeon_bo_map(radeon, bo->bo); + return (uint8_t *) bo->bo->data + bo->offset; + } + + if (p_atomic_read(&bo->bo->reference.count) > 1) { + if (usage & PB_USAGE_DONTBLOCK) { + return NULL; + } + if (ctx) { + pctx->flush(pctx, NULL); + } + } + + if (usage & PB_USAGE_DONTBLOCK) { + uint32_t domain; + + if (radeon_bo_busy(radeon, bo->bo, &domain)) + return NULL; + if (radeon_bo_map(radeon, bo->bo)) { + return NULL; + } + goto out; + } + + radeon_bo_map(radeon, bo->bo); + if (radeon_bo_wait(radeon, bo->bo)) { + radeon_bo_unmap(radeon, bo->bo); + return NULL; + } + +out: + return (uint8_t *) bo->bo->data + bo->offset; } void r600_bo_unmap(struct radeon *radeon, struct r600_bo *bo) { - pb_unmap(bo->pb); + radeon_bo_unmap(radeon, bo->bo); } -static void r600_bo_destroy(struct radeon *radeon, struct r600_bo *bo) +void r600_bo_destroy(struct radeon *radeon, struct r600_bo *bo) { - if (bo->pb) - pb_reference(&bo->pb, NULL); + if (bo->manager_id) { + if (!r600_bomgr_bo_destroy(radeon->bomgr, bo)) { + /* destroy is delayed by buffer manager */ + return; + } + } + radeon_bo_reference(radeon, &bo->bo, NULL); free(bo); } -void r600_bo_reference(struct radeon *radeon, struct r600_bo **dst, - struct r600_bo *src) +void r600_bo_reference(struct radeon *radeon, struct r600_bo **dst, struct r600_bo *src) { struct r600_bo *old = *dst; - + if (pipe_reference(&(*dst)->reference, &src->reference)) { r600_bo_destroy(radeon, old); } *dst = src; } -unsigned r600_bo_get_handle(struct r600_bo *pb_bo) -{ - struct radeon_bo *bo; - - bo = radeon_bo_pb_get_bo(pb_bo->pb); - if (!bo) - return 0; - - return bo->handle; -} - -unsigned r600_bo_get_size(struct r600_bo *pb_bo) -{ - struct radeon_bo *bo; - - bo = radeon_bo_pb_get_bo(pb_bo->pb); - if (!bo) - return 0; - - return bo->size; -} - -boolean r600_bo_get_winsys_handle(struct radeon *radeon, struct r600_bo *pb_bo, +boolean r600_bo_get_winsys_handle(struct radeon *radeon, struct r600_bo *bo, unsigned stride, struct winsys_handle *whandle) { - struct radeon_bo *bo; - - bo = radeon_bo_pb_get_bo(pb_bo->pb); - if (!bo) - return FALSE; - whandle->stride = stride; switch(whandle->type) { case DRM_API_HANDLE_TYPE_KMS: - whandle->handle = r600_bo_get_handle(pb_bo); + whandle->handle = r600_bo_get_handle(bo); break; case DRM_API_HANDLE_TYPE_SHARED: - if (radeon_bo_get_name(radeon, bo, &whandle->handle)) + if (radeon_bo_get_name(radeon, bo->bo, &whandle->handle)) return FALSE; break; default: diff --git a/src/gallium/winsys/r600/drm/r600_bomgr.c b/src/gallium/winsys/r600/drm/r600_bomgr.c new file mode 100644 index 0000000000..446ef0f9cf --- /dev/null +++ b/src/gallium/winsys/r600/drm/r600_bomgr.c @@ -0,0 +1,161 @@ +/* + * Copyright 2010 VMWare. + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jose Fonseca <jrfonseca-at-vmware-dot-com> + * Thomas Hellström <thomas-at-vmware-dot-com> + * Jerome Glisse <jglisse@redhat.com> + */ +#include <util/u_memory.h> +#include <util/u_double_list.h> +#include <util/u_time.h> +#include <pipebuffer/pb_bufmgr.h> +#include "r600_priv.h" + +static void r600_bomgr_timeout_flush(struct r600_bomgr *mgr) +{ + struct r600_bo *bo, *tmp; + int64_t now; + + now = os_time_get(); + LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &mgr->delayed, list) { + if(!os_time_timeout(bo->start, bo->end, now)) + break; + + mgr->num_delayed--; + bo->manager_id = 0; + LIST_DEL(&bo->list); + r600_bo_destroy(mgr->radeon, bo); + } +} + +static INLINE int r600_bo_is_compat(struct r600_bomgr *mgr, + struct r600_bo *bo, + unsigned size, + unsigned alignment, + unsigned cfence) +{ + if(bo->size < size) { + return 0; + } + + /* be lenient with size */ + if(bo->size >= 2*size) { + return 0; + } + + if(!pb_check_alignment(alignment, bo->alignment)) { + return 0; + } + + if (!fence_is_after(cfence, bo->fence)) { + return 0; + } + + return 1; +} + +struct r600_bo *r600_bomgr_bo_create(struct r600_bomgr *mgr, + unsigned size, + unsigned alignment, + unsigned cfence) +{ + struct r600_bo *bo, *tmp; + int64_t now; + + + pipe_mutex_lock(mgr->mutex); + + now = os_time_get(); + LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &mgr->delayed, list) { + if(r600_bo_is_compat(mgr, bo, size, alignment, cfence)) { + LIST_DEL(&bo->list); + --mgr->num_delayed; + r600_bomgr_timeout_flush(mgr); + pipe_mutex_unlock(mgr->mutex); + LIST_INITHEAD(&bo->list); + pipe_reference_init(&bo->reference, 1); + return bo; + } + + if(os_time_timeout(bo->start, bo->end, now)) { + mgr->num_delayed--; + bo->manager_id = 0; + LIST_DEL(&bo->list); + r600_bo_destroy(mgr->radeon, bo); + } + } + + pipe_mutex_unlock(mgr->mutex); + return NULL; +} + +void r600_bomgr_bo_init(struct r600_bomgr *mgr, struct r600_bo *bo) +{ + LIST_INITHEAD(&bo->list); + bo->manager_id = 1; +} + +bool r600_bomgr_bo_destroy(struct r600_bomgr *mgr, struct r600_bo *bo) +{ + bo->start = os_time_get(); + bo->end = bo->start + mgr->usecs; + pipe_mutex_lock(mgr->mutex); + LIST_ADDTAIL(&bo->list, &mgr->delayed); + ++mgr->num_delayed; + pipe_mutex_unlock(mgr->mutex); + return FALSE; +} + +void r600_bomgr_destroy(struct r600_bomgr *mgr) +{ + struct r600_bo *bo, *tmp; + + pipe_mutex_lock(mgr->mutex); + LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &mgr->delayed, list) { + mgr->num_delayed--; + bo->manager_id = 0; + LIST_DEL(&bo->list); + r600_bo_destroy(mgr->radeon, bo); + } + pipe_mutex_unlock(mgr->mutex); + + FREE(mgr); +} + +struct r600_bomgr *r600_bomgr_create(struct radeon *radeon, unsigned usecs) +{ + struct r600_bomgr *mgr; + + mgr = CALLOC_STRUCT(r600_bomgr); + if (mgr == NULL) + return NULL; + + mgr->radeon = radeon; + mgr->usecs = usecs; + LIST_INITHEAD(&mgr->delayed); + mgr->num_delayed = 0; + pipe_mutex_init(mgr->mutex); + + return mgr; +} diff --git a/src/gallium/winsys/r600/drm/r600_drm.c b/src/gallium/winsys/r600/drm/r600_drm.c index 8c847122f8..c081abb4dc 100644 --- a/src/gallium/winsys/r600/drm/r600_drm.c +++ b/src/gallium/winsys/r600/drm/r600_drm.c @@ -41,11 +41,48 @@ #define RADEON_INFO_TILING_CONFIG 0x6 #endif -static struct radeon *radeon_new(int fd, unsigned device); +#ifndef RADEON_INFO_CLOCK_CRYSTAL_FREQ +#define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x9 +#endif + +#ifndef RADEON_INFO_NUM_BACKENDS +#define RADEON_INFO_NUM_BACKENDS 0xa +#endif + +enum radeon_family r600_get_family(struct radeon *r600) +{ + return r600->family; +} + +enum chip_class r600_get_family_class(struct radeon *radeon) +{ + return radeon->chip_class; +} + +struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon) +{ + return &radeon->tiling_info; +} + +unsigned r600_get_clock_crystal_freq(struct radeon *radeon) +{ + return radeon->clock_crystal_freq; +} + +unsigned r600_get_num_backends(struct radeon *radeon) +{ + return radeon->num_backends; +} + +unsigned r600_get_minor_version(struct radeon *radeon) +{ + return radeon->minor_version; +} + static int radeon_get_device(struct radeon *radeon) { - struct drm_radeon_info info; + struct drm_radeon_info info = {}; int r; radeon->device = 0; @@ -56,20 +93,8 @@ static int radeon_get_device(struct radeon *radeon) return r; } -static int radeon_drm_get_tiling(struct radeon *radeon) +static int r600_interpret_tiling(struct radeon *radeon, uint32_t tiling_config) { - struct drm_radeon_info info; - int r; - uint32_t tiling_config; - - info.request = RADEON_INFO_TILING_CONFIG; - info.value = (uintptr_t)&tiling_config; - r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info, - sizeof(struct drm_radeon_info)); - - if (r) - return 0; - switch ((tiling_config & 0xe) >> 1) { case 0: radeon->tiling_info.num_channels = 1; @@ -111,10 +136,117 @@ static int radeon_drm_get_tiling(struct radeon *radeon) return 0; } +static int eg_interpret_tiling(struct radeon *radeon, uint32_t tiling_config) +{ + switch (tiling_config & 0xf) { + case 0: + radeon->tiling_info.num_channels = 1; + break; + case 1: + radeon->tiling_info.num_channels = 2; + break; + case 2: + radeon->tiling_info.num_channels = 4; + break; + case 3: + radeon->tiling_info.num_channels = 8; + break; + default: + return -EINVAL; + } + + radeon->tiling_info.num_banks = (tiling_config & 0xf0) >> 4; + + switch ((tiling_config & 0xf00) >> 8) { + case 0: + radeon->tiling_info.group_bytes = 256; + break; + case 1: + radeon->tiling_info.group_bytes = 512; + break; + default: + return -EINVAL; + } + return 0; +} + +static int radeon_drm_get_tiling(struct radeon *radeon) +{ + struct drm_radeon_info info; + int r; + uint32_t tiling_config = 0; + + info.request = RADEON_INFO_TILING_CONFIG; + info.value = (uintptr_t)&tiling_config; + r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info, + sizeof(struct drm_radeon_info)); + + if (r) + return 0; + + if (radeon->chip_class == R600 || radeon->chip_class == R700) { + r = r600_interpret_tiling(radeon, tiling_config); + } else { + r = eg_interpret_tiling(radeon, tiling_config); + } + return r; +} + +static int radeon_get_clock_crystal_freq(struct radeon *radeon) +{ + struct drm_radeon_info info; + uint32_t clock_crystal_freq; + int r; + + radeon->device = 0; + info.request = RADEON_INFO_CLOCK_CRYSTAL_FREQ; + info.value = (uintptr_t)&clock_crystal_freq; + r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info, + sizeof(struct drm_radeon_info)); + if (r) + return r; + + radeon->clock_crystal_freq = clock_crystal_freq; + return 0; +} + + +static int radeon_get_num_backends(struct radeon *radeon) +{ + struct drm_radeon_info info; + uint32_t num_backends; + int r; + + radeon->device = 0; + info.request = RADEON_INFO_NUM_BACKENDS; + info.value = (uintptr_t)&num_backends; + r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info, + sizeof(struct drm_radeon_info)); + if (r) + return r; + + radeon->num_backends = num_backends; + return 0; +} + + +static int radeon_init_fence(struct radeon *radeon) +{ + radeon->fence = 1; + radeon->fence_bo = r600_bo(radeon, 4096, 0, 0, 0); + if (radeon->fence_bo == NULL) { + return -ENOMEM; + } + radeon->cfence = r600_bo_map(radeon, radeon->fence_bo, PB_USAGE_UNSYNCHRONIZED, NULL); + *radeon->cfence = 0; + return 0; +} + static struct radeon *radeon_new(int fd, unsigned device) { struct radeon *radeon; int r; + drmVersionPtr version; radeon = calloc(1, sizeof(*radeon)); if (radeon == NULL) { @@ -123,71 +255,32 @@ static struct radeon *radeon_new(int fd, unsigned device) radeon->fd = fd; radeon->device = device; radeon->refcount = 1; - if (fd >= 0) { - r = radeon_get_device(radeon); - if (r) { - fprintf(stderr, "Failed to get device id\n"); - return radeon_decref(radeon); - } + + version = drmGetVersion(radeon->fd); + if (version->version_major != 2) { + fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is " + "only compatible with 2.x.x\n", __FUNCTION__, + version->version_major, version->version_minor, + version->version_patchlevel); + drmFreeVersion(version); + exit(1); + } + + radeon->minor_version = version->version_minor; + + drmFreeVersion(version); + + r = radeon_get_device(radeon); + if (r) { + fprintf(stderr, "Failed to get device id\n"); + return radeon_decref(radeon); } + radeon->family = radeon_family_from_device(radeon->device); if (radeon->family == CHIP_UNKNOWN) { fprintf(stderr, "Unknown chipset 0x%04X\n", radeon->device); return radeon_decref(radeon); } - switch (radeon->family) { - 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: - case CHIP_CEDAR: - case CHIP_REDWOOD: - case CHIP_JUNIPER: - case CHIP_CYPRESS: - case CHIP_HEMLOCK: - case CHIP_PALM: - break; - case CHIP_R100: - case CHIP_RV100: - case CHIP_RS100: - case CHIP_RV200: - case CHIP_RS200: - case CHIP_R200: - case CHIP_RV250: - case CHIP_RS300: - case CHIP_RV280: - case CHIP_R300: - case CHIP_R350: - case CHIP_RV350: - case CHIP_RV380: - case CHIP_R420: - case CHIP_R423: - case CHIP_RV410: - case CHIP_RS400: - case CHIP_RS480: - case CHIP_RS600: - case CHIP_RS690: - case CHIP_RS740: - case CHIP_RV515: - case CHIP_R520: - case CHIP_RV530: - case CHIP_RV560: - case CHIP_RV570: - case CHIP_R580: - default: - fprintf(stderr, "%s unknown or unsupported chipset 0x%04X\n", - __func__, radeon->device); - break; - } - /* setup class */ switch (radeon->family) { case CHIP_R600: @@ -216,6 +309,9 @@ static struct radeon *radeon_new(int fd, unsigned device) case CHIP_CYPRESS: case CHIP_HEMLOCK: case CHIP_PALM: + case CHIP_BARTS: + case CHIP_TURKS: + case CHIP_CAICOS: radeon->chip_class = EVERGREEN; /* set default group bytes, overridden by tiling info ioctl */ radeon->tiling_info.group_bytes = 512; @@ -226,16 +322,24 @@ static struct radeon *radeon_new(int fd, unsigned device) break; } - if (radeon->chip_class == R600 || radeon->chip_class == R700) { - if (radeon_drm_get_tiling(radeon)) - return NULL; - } - radeon->kman = radeon_bo_pbmgr_create(radeon); - if (!radeon->kman) + if (radeon_drm_get_tiling(radeon)) return NULL; - radeon->cman = pb_cache_manager_create(radeon->kman, 1000000); - if (!radeon->cman) + + /* get the GPU counter frequency, failure is non fatal */ + radeon_get_clock_crystal_freq(radeon); + + if (radeon->minor_version >= 9) + radeon_get_num_backends(radeon); + + radeon->bomgr = r600_bomgr_create(radeon, 1000000); + if (radeon->bomgr == NULL) { return NULL; + } + r = radeon_init_fence(radeon); + if (r) { + radeon_decref(radeon); + return NULL; + } return radeon; } @@ -252,14 +356,12 @@ struct radeon *radeon_decref(struct radeon *radeon) return NULL; } - if (radeon->cman) - radeon->cman->destroy(radeon->cman); - - if (radeon->kman) - radeon->kman->destroy(radeon->kman); + if (radeon->fence_bo) { + r600_bo_reference(radeon, &radeon->fence_bo, NULL); + } - if (radeon->fd >= 0) - drmClose(radeon->fd); + if (radeon->bomgr) + r600_bomgr_destroy(radeon->bomgr); free(radeon); return NULL; diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c b/src/gallium/winsys/r600/drm/r600_hw_context.c index 0f2724f61c..a7c21784e5 100644 --- a/src/gallium/winsys/r600/drm/r600_hw_context.c +++ b/src/gallium/winsys/r600/drm/r600_hw_context.c @@ -28,39 +28,25 @@ #include <string.h> #include <stdlib.h> #include <assert.h> +#include <pipe/p_compiler.h> +#include <util/u_inlines.h> +#include <util/u_memory.h> +#include <pipebuffer/pb_bufmgr.h> #include "xf86drm.h" -#include "r600.h" -#include "r600d.h" #include "radeon_drm.h" -#include "bof.h" -#include "pipe/p_compiler.h" -#include "util/u_inlines.h" -#include "util/u_memory.h" -#include <pipebuffer/pb_bufmgr.h> #include "r600_priv.h" +#include "bof.h" +#include "r600d.h" #define GROUP_FORCE_NEW_BLOCK 0 -int r600_context_init_fence(struct r600_context *ctx) -{ - ctx->fence = 1; - ctx->fence_bo = r600_bo(ctx->radeon, 4096, 0, 0, 0); - if (ctx->fence_bo == NULL) { - return -ENOMEM; - } - ctx->cfence = r600_bo_map(ctx->radeon, ctx->fence_bo, PB_USAGE_UNSYNCHRONIZED, NULL); - *ctx->cfence = 0; - LIST_INITHEAD(&ctx->fenced_bo); - return 0; -} - static void INLINE r600_context_update_fenced_list(struct r600_context *ctx) { for (int i = 0; i < ctx->creloc; i++) { if (!LIST_IS_EMPTY(&ctx->bo[i]->fencedlist)) LIST_DELINIT(&ctx->bo[i]->fencedlist); LIST_ADDTAIL(&ctx->bo[i]->fencedlist, &ctx->fenced_bo); - ctx->bo[i]->fence = ctx->fence; + ctx->bo[i]->fence = ctx->radeon->fence; ctx->bo[i]->ctx = ctx; } } @@ -71,7 +57,7 @@ static void INLINE r600_context_fence_wraparound(struct r600_context *ctx, unsig struct radeon_bo *tmp; LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &ctx->fenced_bo, fencedlist) { - if (bo->fence <= *ctx->cfence) { + if (bo->fence <= *ctx->radeon->cfence) { LIST_DELINIT(&bo->fencedlist); bo->fence = 0; } else { @@ -121,7 +107,7 @@ int r600_context_add_block(struct r600_context *ctx, const struct r600_reg *reg, /* initialize block */ block->start_offset = reg[i].offset; - block->pm4[block->pm4_ndwords++] = PKT3(reg[i].opcode, n); + block->pm4[block->pm4_ndwords++] = PKT3(reg[i].opcode, n, 0); block->pm4[block->pm4_ndwords++] = (block->start_offset - reg[i].offset_base) >> 2; block->reg = &block->pm4[block->pm4_ndwords]; block->pm4_ndwords += n; @@ -133,7 +119,7 @@ int r600_context_add_block(struct r600_context *ctx, const struct r600_reg *reg, block->nbo++; assert(block->nbo < R600_BLOCK_MAX_BO); block->pm4_bo_index[j] = block->nbo; - block->pm4[block->pm4_ndwords++] = PKT3(PKT3_NOP, 0); + block->pm4[block->pm4_ndwords++] = PKT3(PKT3_NOP, 0, 0); block->pm4[block->pm4_ndwords++] = 0x00000000; block->reloc[block->nbo].flush_flags = reg[i+j].flush_flags; block->reloc[block->nbo].flush_mask = reg[i+j].flush_mask; @@ -632,9 +618,6 @@ void r600_context_fini(struct r600_context *ctx) free(ctx->pm4); r600_context_clear_fenced_bo(ctx); - if (ctx->fence_bo) { - r600_bo_reference(ctx->radeon, &ctx->fence_bo, NULL); - } memset(ctx, 0, sizeof(struct r600_context)); } @@ -654,7 +637,8 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon) ctx->range[i].end_offset = ((i + 1) << ctx->hash_shift) - 1; ctx->range[i].blocks = calloc(1 << ctx->hash_shift, sizeof(void*)); if (ctx->range[i].blocks == NULL) { - return -ENOMEM; + r = -ENOMEM; + goto out_err; } } @@ -763,19 +747,30 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon) /* save 16dwords space for fence mecanism */ ctx->pm4_ndwords -= 16; - r = r600_context_init_fence(ctx); - if (r) { - goto out_err; - } + LIST_INITHEAD(&ctx->fenced_bo); /* init dirty list */ LIST_INITHEAD(&ctx->dirty); + + ctx->max_db = 4; + return 0; out_err: r600_context_fini(ctx); return r; } +static void rv6xx_context_surface_base_update(struct r600_context *ctx, + unsigned base_update_flags) +{ + /* need to emit surface base update on rv6xx */ + if ((ctx->radeon->family > CHIP_R600) && + (ctx->radeon->family < CHIP_RV770)) { + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_SURFACE_BASE_UPDATE, 0, 0); + ctx->pm4[ctx->pm4_cdwords++] = base_update_flags; + } +} + void r600_context_bo_flush(struct r600_context *ctx, unsigned flush_flags, unsigned flush_mask, struct r600_bo *rbo) { @@ -787,12 +782,12 @@ void r600_context_bo_flush(struct r600_context *ctx, unsigned flush_flags, bo->last_flush &= flush_mask; return; } - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_SURFACE_SYNC, 3); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_SURFACE_SYNC, 3, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = flush_flags; ctx->pm4[ctx->pm4_cdwords++] = (bo->size + 255) >> 8; ctx->pm4[ctx->pm4_cdwords++] = 0x00000000; ctx->pm4[ctx->pm4_cdwords++] = 0x0000000A; - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = bo->reloc_id; bo->last_flush = (bo->last_flush | flush_flags) & flush_mask; } @@ -814,6 +809,7 @@ void r600_context_bo_reloc(struct r600_context *ctx, u32 *pm4, struct r600_bo *r ctx->reloc[ctx->creloc].write_domain = rbo->domains & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM); ctx->reloc[ctx->creloc].flags = 0; radeon_bo_reference(ctx->radeon, &ctx->bo[ctx->creloc], bo); + rbo->fence = ctx->radeon->fence; ctx->creloc++; /* set PKT3 to point to proper reloc */ *pm4 = bo->reloc_id; @@ -836,6 +832,7 @@ void r600_context_pipe_state_set(struct r600_context *ctx, struct r600_pipe_stat /* find relocation */ id = block->pm4_bo_index[id]; r600_bo_reference(ctx->radeon, &block->reloc[id].bo, state->regs[i].bo); + state->regs[i].bo->fence = ctx->radeon->fence; } if (!(block->status & R600_BLOCK_STATUS_DIRTY)) { block->status |= R600_BLOCK_STATUS_ENABLED; @@ -875,10 +872,13 @@ static inline void r600_context_pipe_state_set_resource(struct r600_context *ctx */ r600_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[0].bo); r600_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[0].bo); + state->regs[0].bo->fence = ctx->radeon->fence; } else { /* TEXTURE RESOURCE */ r600_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[2].bo); r600_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[3].bo); + state->regs[2].bo->fence = ctx->radeon->fence; + state->regs[3].bo->fence = ctx->radeon->fence; } if (!(block->status & R600_BLOCK_STATUS_DIRTY)) { block->status |= R600_BLOCK_STATUS_ENABLED; @@ -1002,6 +1002,7 @@ void r600_context_draw(struct r600_context *ctx, const struct r600_draw *draw) unsigned ndwords = 9; struct r600_block *dirty_block = NULL; struct r600_block *next_block; + unsigned rv6xx_surface_base_update = 0; if (draw->indices) { ndwords = 13; @@ -1024,10 +1025,14 @@ void r600_context_draw(struct r600_context *ctx, const struct r600_draw *draw) for (int i = 0; i < 8; i++) { if (cb[i]) { ndwords += 7; + rv6xx_surface_base_update |= SURFACE_BASE_UPDATE_COLOR(i); } } - if (db) + if (db) { ndwords += 7; + rv6xx_surface_base_update |= SURFACE_BASE_UPDATE_DEPTH; + } + /* XXX also need to update SURFACE_BASE_UPDATE_STRMOUT when we support it */ /* queries need some special values */ if (ctx->num_query_running) { @@ -1054,30 +1059,34 @@ void r600_context_draw(struct r600_context *ctx, const struct r600_draw *draw) } /* enough room to copy packet */ - LIST_FOR_EACH_ENTRY_SAFE(dirty_block, next_block, &ctx->dirty,list) { + LIST_FOR_EACH_ENTRY_SAFE(dirty_block, next_block, &ctx->dirty, list) { r600_context_block_emit_dirty(ctx, dirty_block); } + /* rv6xx surface base udpate */ + if (rv6xx_surface_base_update) + rv6xx_context_surface_base_update(ctx, rv6xx_surface_base_update); + /* draw packet */ - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_INDEX_TYPE, 0); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_INDEX_TYPE, 0, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_index_type; - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NUM_INSTANCES, 0); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NUM_INSTANCES, 0, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_num_instances; if (draw->indices) { - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_DRAW_INDEX, 3); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_DRAW_INDEX, 3, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = draw->indices_bo_offset + r600_bo_offset(draw->indices); ctx->pm4[ctx->pm4_cdwords++] = 0; ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_num_indices; ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_draw_initiator; - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = 0; r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], draw->indices); } else { - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_DRAW_INDEX_AUTO, 1); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_DRAW_INDEX_AUTO, 1, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_num_indices; ctx->pm4[ctx->pm4_cdwords++] = draw->vgt_draw_initiator; } - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 0); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 0, ctx->predicate_drawing); ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0); /* flush color buffer */ @@ -1099,7 +1108,7 @@ void r600_context_draw(struct r600_context *ctx, const struct r600_draw *draw) void r600_context_flush(struct r600_context *ctx) { - struct drm_radeon_cs drmib; + struct drm_radeon_cs drmib = {}; struct drm_radeon_cs_chunk chunks[2]; uint64_t chunk_array[2]; unsigned fence; @@ -1112,17 +1121,17 @@ void r600_context_flush(struct r600_context *ctx) r600_context_queries_suspend(ctx); /* emit fence */ - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 0); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 0, 0); ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_PS_PARTIAL_FLUSH) | EVENT_INDEX(4); - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4, 0); ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5); ctx->pm4[ctx->pm4_cdwords++] = 0; ctx->pm4[ctx->pm4_cdwords++] = (1 << 29) | (0 << 24); - ctx->pm4[ctx->pm4_cdwords++] = ctx->fence; + ctx->pm4[ctx->pm4_cdwords++] = ctx->radeon->fence; ctx->pm4[ctx->pm4_cdwords++] = 0; - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0); + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0, 0); ctx->pm4[ctx->pm4_cdwords++] = 0; - r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], ctx->fence_bo); + r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], ctx->radeon->fence_bo); #if 1 /* emit cs */ @@ -1139,18 +1148,18 @@ void r600_context_flush(struct r600_context *ctx) r = drmCommandWriteRead(ctx->radeon->fd, DRM_RADEON_CS, &drmib, sizeof(struct drm_radeon_cs)); #else - *ctx->cfence = ctx->fence; + *ctx->radeon->cfence = ctx->radeon->fence; #endif r600_context_update_fenced_list(ctx); - fence = ctx->fence + 1; - if (fence < ctx->fence) { + fence = ctx->radeon->fence + 1; + if (fence < ctx->radeon->fence) { /* wrap around */ fence = 1; r600_context_fence_wraparound(ctx, fence); } - ctx->fence = fence; + ctx->radeon->fence = fence; /* restart */ for (int i = 0; i < ctx->creloc; i++) { @@ -1261,44 +1270,90 @@ out_err: bof_decref(root); } -static void r600_query_result(struct r600_context *ctx, struct r600_query *query) +static boolean r600_query_result(struct r600_context *ctx, struct r600_query *query, boolean wait) { u64 start, end; u32 *results; int i; + int size; + + if (wait) + results = r600_bo_map(ctx->radeon, query->buffer, PB_USAGE_CPU_READ, NULL); + else + results = r600_bo_map(ctx->radeon, query->buffer, PB_USAGE_DONTBLOCK | PB_USAGE_CPU_READ, NULL); + if (!results) + return FALSE; - results = r600_bo_map(ctx->radeon, query->buffer, 0, NULL); - for (i = 0; i < query->num_results; i += 4) { + size = query->num_results * (query->type == PIPE_QUERY_OCCLUSION_COUNTER ? ctx->max_db : 1); + for (i = 0; i < size; i += 4) { start = (u64)results[i] | (u64)results[i + 1] << 32; end = (u64)results[i + 2] | (u64)results[i + 3] << 32; - if ((start & 0x8000000000000000UL) && (end & 0x8000000000000000UL)) { + if (((start & 0x8000000000000000UL) && (end & 0x8000000000000000UL)) + || query->type == PIPE_QUERY_TIME_ELAPSED) { query->result += end - start; } } r600_bo_unmap(ctx->radeon, query->buffer); query->num_results = 0; + + return TRUE; } void r600_query_begin(struct r600_context *ctx, struct r600_query *query) { - /* query request needs 6 dwords for begin + 6 dwords for end */ - if ((12 + ctx->pm4_cdwords) > ctx->pm4_ndwords) { + unsigned required_space; + int num_backends = r600_get_num_backends(ctx->radeon); + + /* query request needs 6/8 dwords for begin + 6/8 dwords for end */ + if (query->type == PIPE_QUERY_TIME_ELAPSED) + required_space = 16; + else + required_space = 12; + + if ((required_space + ctx->pm4_cdwords) > ctx->pm4_ndwords) { /* need to flush */ r600_context_flush(ctx); } /* if query buffer is full force a flush */ - if (query->num_results >= ((query->buffer_size >> 2) - 2)) { + if (query->num_results*4 >= query->buffer_size - 16) { r600_context_flush(ctx); - r600_query_result(ctx, query); + r600_query_result(ctx, query, TRUE); } + if (query->type == PIPE_QUERY_OCCLUSION_COUNTER && + num_backends > 0 && num_backends < ctx->max_db) { + /* as per info on ZPASS the driver must set the unusued DB top bits */ + u32 *results; + int i; + + results = r600_bo_map(ctx->radeon, query->buffer, PB_USAGE_DONTBLOCK | PB_USAGE_CPU_WRITE, NULL); + if (results) { + memset(results + (query->num_results * 4), 0, ctx->max_db * 4 * 4); + + for (i = num_backends; i < ctx->max_db; i++) { + results[(i * 4)+1] = 0x80000000; + results[(i * 4)+3] = 0x80000000; + } + r600_bo_unmap(ctx->radeon, query->buffer); + } + } + /* emit begin query */ - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2); - ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1); - ctx->pm4[ctx->pm4_cdwords++] = query->num_results + r600_bo_offset(query->buffer); - ctx->pm4[ctx->pm4_cdwords++] = 0; - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0); + if (query->type == PIPE_QUERY_TIME_ELAPSED) { + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4, 0); + ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5); + ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + r600_bo_offset(query->buffer); + ctx->pm4[ctx->pm4_cdwords++] = (3 << 29); + ctx->pm4[ctx->pm4_cdwords++] = 0; + ctx->pm4[ctx->pm4_cdwords++] = 0; + } else { + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2, 0); + ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1); + ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + r600_bo_offset(query->buffer); + ctx->pm4[ctx->pm4_cdwords++] = 0; + } + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0, 0); ctx->pm4[ctx->pm4_cdwords++] = 0; r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], query->buffer); @@ -1310,25 +1365,56 @@ void r600_query_begin(struct r600_context *ctx, struct r600_query *query) void r600_query_end(struct r600_context *ctx, struct r600_query *query) { /* emit begin query */ - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2); - ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1); - ctx->pm4[ctx->pm4_cdwords++] = query->num_results + 8 + r600_bo_offset(query->buffer); - ctx->pm4[ctx->pm4_cdwords++] = 0; - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0); + if (query->type == PIPE_QUERY_TIME_ELAPSED) { + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4, 0); + ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5); + ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + 8 + r600_bo_offset(query->buffer); + ctx->pm4[ctx->pm4_cdwords++] = (3 << 29); + ctx->pm4[ctx->pm4_cdwords++] = 0; + ctx->pm4[ctx->pm4_cdwords++] = 0; + } else { + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2, 0); + ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1); + ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + 8 + r600_bo_offset(query->buffer); + ctx->pm4[ctx->pm4_cdwords++] = 0; + } + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0, 0); ctx->pm4[ctx->pm4_cdwords++] = 0; r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], query->buffer); - query->num_results += 16; + query->num_results += 4 * (query->type == PIPE_QUERY_OCCLUSION_COUNTER ? ctx->max_db : 1); query->state ^= R600_QUERY_STATE_STARTED; query->state |= R600_QUERY_STATE_ENDED; ctx->num_query_running--; } +void r600_query_predication(struct r600_context *ctx, struct r600_query *query, int operation, + int flag_wait) +{ + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_SET_PREDICATION, 1, 0); + + if (operation == PREDICATION_OP_CLEAR) { + ctx->pm4[ctx->pm4_cdwords++] = 0; + ctx->pm4[ctx->pm4_cdwords++] = PRED_OP(PREDICATION_OP_CLEAR); + } else { + int results_base = query->num_results - (4 * ctx->max_db); + + if (results_base < 0) + results_base = 0; + + ctx->pm4[ctx->pm4_cdwords++] = results_base*4 + r600_bo_offset(query->buffer); + ctx->pm4[ctx->pm4_cdwords++] = PRED_OP(operation) | (flag_wait ? PREDICATION_HINT_WAIT : PREDICATION_HINT_NOWAIT_DRAW) | PREDICATION_DRAW_VISIBLE; + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0, 0); + ctx->pm4[ctx->pm4_cdwords++] = 0; + r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], query->buffer); + } +} + struct r600_query *r600_context_query_create(struct r600_context *ctx, unsigned query_type) { struct r600_query *query; - if (query_type != PIPE_QUERY_OCCLUSION_COUNTER) + if (query_type != PIPE_QUERY_OCCLUSION_COUNTER && query_type != PIPE_QUERY_TIME_ELAPSED) return NULL; query = calloc(1, sizeof(struct r600_query)); @@ -1370,8 +1456,12 @@ boolean r600_context_query_result(struct r600_context *ctx, if (query->num_results) { r600_context_flush(ctx); } - r600_query_result(ctx, query); - *result = query->result; + if (!r600_query_result(ctx, query, wait)) + return FALSE; + if (query->type == PIPE_QUERY_TIME_ELAPSED) + *result = (1000000*query->result)/r600_get_clock_crystal_freq(ctx->radeon); + else + *result = query->result; query->result = 0; return TRUE; } diff --git a/src/gallium/winsys/r600/drm/r600_priv.h b/src/gallium/winsys/r600/drm/r600_priv.h index 193af984f8..41c5ee02c3 100644 --- a/src/gallium/winsys/r600/drm/r600_priv.h +++ b/src/gallium/winsys/r600/drm/r600_priv.h @@ -30,24 +30,30 @@ #include <stdint.h> #include <stdlib.h> #include <assert.h> -#include <pipebuffer/pb_bufmgr.h> -#include "util/u_double_list.h" +#include <util/u_double_list.h> +#include <util/u_inlines.h> +#include <os/os_thread.h> #include "r600.h" +struct r600_bomgr; +struct r600_bo; + struct radeon { int fd; int refcount; unsigned device; unsigned family; enum chip_class chip_class; - struct pb_manager *kman; /* kernel bo manager */ - struct pb_manager *cman; /* cached bo manager */ - struct r600_tiling_info tiling_info; + struct r600_tiling_info tiling_info; + struct r600_bomgr *bomgr; + unsigned fence; + unsigned *cfence; + struct r600_bo *fence_bo; + unsigned clock_crystal_freq; + unsigned num_backends; + unsigned minor_version; }; -struct radeon *r600_new(int fd, unsigned device); -void r600_delete(struct radeon *r600); - struct r600_reg { unsigned opcode; unsigned offset_base; @@ -75,25 +81,49 @@ struct radeon_bo { struct r600_bo { struct pipe_reference reference; - struct pb_buffer *pb; unsigned size; unsigned tiling_flags; unsigned kernel_pitch; unsigned domains; + struct radeon_bo *bo; + unsigned fence; + /* manager data */ + struct list_head list; + unsigned manager_id; + unsigned alignment; + unsigned offset; + int64_t start; + int64_t end; }; +struct r600_bomgr { + struct radeon *radeon; + unsigned usecs; + pipe_mutex mutex; + struct list_head delayed; + unsigned num_delayed; +}; -/* radeon_pciid.c */ +/* + * r600_drm.c + */ +struct radeon *r600_new(int fd, unsigned device); +void r600_delete(struct radeon *r600); + +/* + * radeon_pciid.c + */ unsigned radeon_family_from_device(unsigned device); -/* radeon_bo.c */ +/* + * radeon_bo.c + */ struct radeon_bo *radeon_bo(struct radeon *radeon, unsigned handle, unsigned size, unsigned alignment); void radeon_bo_reference(struct radeon *radeon, struct radeon_bo **dst, struct radeon_bo *src); int radeon_bo_wait(struct radeon *radeon, struct radeon_bo *bo); int radeon_bo_busy(struct radeon *radeon, struct radeon_bo *bo, uint32_t *domain); -void radeon_bo_pbmgr_flush_maps(struct pb_manager *_mgr); int radeon_bo_fencelist(struct radeon *radeon, struct radeon_bo **bolist, uint32_t num_bo); int radeon_bo_get_tiling_flags(struct radeon *radeon, struct radeon_bo *bo, @@ -103,13 +133,9 @@ int radeon_bo_get_name(struct radeon *radeon, struct radeon_bo *bo, uint32_t *name); -/* radeon_bo_pb.c */ -struct radeon_bo *radeon_bo_pb_get_bo(struct pb_buffer *_buf); -struct pb_manager *radeon_bo_pbmgr_create(struct radeon *radeon); -struct pb_buffer *radeon_bo_pb_create_buffer_from_handle(struct pb_manager *_mgr, - uint32_t handle); - -/* r600_hw_context.c */ +/* + * r600_hw_context.c + */ int r600_context_init_fence(struct r600_context *ctx); void r600_context_bo_reloc(struct r600_context *ctx, u32 *pm4, struct r600_bo *rbo); void r600_context_bo_flush(struct r600_context *ctx, unsigned flush_flags, @@ -117,14 +143,27 @@ void r600_context_bo_flush(struct r600_context *ctx, unsigned flush_flags, struct r600_bo *r600_context_reg_bo(struct r600_context *ctx, unsigned offset); int r600_context_add_block(struct r600_context *ctx, const struct r600_reg *reg, unsigned nreg); -/* r600_bo.c */ -unsigned r600_bo_get_handle(struct r600_bo *bo); -unsigned r600_bo_get_size(struct r600_bo *bo); -static INLINE struct radeon_bo *r600_bo_get_bo(struct r600_bo *bo) -{ - return radeon_bo_pb_get_bo(bo->pb); -} +/* + * r600_bo.c + */ +void r600_bo_destroy(struct radeon *radeon, struct r600_bo *bo); +/* + * r600_bomgr.c + */ +struct r600_bomgr *r600_bomgr_create(struct radeon *radeon, unsigned usecs); +void r600_bomgr_destroy(struct r600_bomgr *mgr); +bool r600_bomgr_bo_destroy(struct r600_bomgr *mgr, struct r600_bo *bo); +void r600_bomgr_bo_init(struct r600_bomgr *mgr, struct r600_bo *bo); +struct r600_bo *r600_bomgr_bo_create(struct r600_bomgr *mgr, + unsigned size, + unsigned alignment, + unsigned cfence); + + +/* + * helpers + */ #define CTX_RANGE_ID(ctx, offset) (((offset) >> (ctx)->hash_shift) & 255) #define CTX_BLOCK_ID(ctx, offset) ((offset) & ((1 << (ctx)->hash_shift) - 1)) @@ -172,6 +211,9 @@ static inline void r600_context_block_emit_dirty(struct r600_context *ctx, struc LIST_DELINIT(&block->list); } +/* + * radeon_bo.c + */ static inline int radeon_bo_map(struct radeon *radeon, struct radeon_bo *bo) { bo->map_count++; @@ -184,4 +226,35 @@ static inline void radeon_bo_unmap(struct radeon *radeon, struct radeon_bo *bo) assert(bo->map_count >= 0); } +/* + * r600_bo + */ +static inline struct radeon_bo *r600_bo_get_bo(struct r600_bo *bo) +{ + return bo->bo; +} + +static unsigned inline r600_bo_get_handle(struct r600_bo *bo) +{ + return bo->bo->handle; +} + +static unsigned inline r600_bo_get_size(struct r600_bo *bo) +{ + return bo->size; +} + +/* + * fence + */ +static inline bool fence_is_after(unsigned fence, unsigned ofence) +{ + /* handle wrap around */ + if (fence < 0x80000000 && ofence > 0x80000000) + return TRUE; + if (fence > ofence) + return TRUE; + return FALSE; +} + #endif diff --git a/src/gallium/winsys/r600/drm/r600d.h b/src/gallium/winsys/r600/drm/r600d.h index 1c1ac76fe6..8042481804 100644 --- a/src/gallium/winsys/r600/drm/r600d.h +++ b/src/gallium/winsys/r600/drm/r600d.h @@ -90,6 +90,9 @@ #define PKT3_SET_SAMPLER 0x6E #define PKT3_SET_CTL_CONST 0x6F #define PKT3_SURFACE_BASE_UPDATE 0x73 +#define SURFACE_BASE_UPDATE_DEPTH (1 << 0) +#define SURFACE_BASE_UPDATE_COLOR(x) (2 << (x)) +#define SURFACE_BASE_UPDATE_STRMOUT(x) (0x200 << (x)) #define EVENT_TYPE_PS_PARTIAL_FLUSH 0x10 #define EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT 0x14 @@ -105,6 +108,18 @@ * 5 - TS events */ +#define PREDICATION_OP_CLEAR 0x0 +#define PREDICATION_OP_ZPASS 0x1 +#define PREDICATION_OP_PRIMCOUNT 0x2 + +#define PRED_OP(x) ((x) << 16) + +#define PREDICATION_HINT_WAIT (0 << 12) +#define PREDICATION_HINT_NOWAIT_DRAW (1 << 12) + +#define PREDICATION_DRAW_NOT_VISIBLE (0 << 8) +#define PREDICATION_DRAW_VISIBLE (1 << 8) + #define PKT_TYPE_S(x) (((x) & 0x3) << 30) #define PKT_TYPE_G(x) (((x) >> 30) & 0x3) #define PKT_TYPE_C 0x3FFFFFFF @@ -117,8 +132,9 @@ #define PKT3_IT_OPCODE_S(x) (((x) & 0xFF) << 8) #define PKT3_IT_OPCODE_G(x) (((x) >> 8) & 0xFF) #define PKT3_IT_OPCODE_C 0xFFFF00FF +#define PKT3_PRED_S(x) (((x) >> 0) & 0x1) #define PKT0(index, count) (PKT_TYPE_S(0) | PKT0_BASE_INDEX_S(index) | PKT_COUNT_S(count)) -#define PKT3(op, count) (PKT_TYPE_S(3) | PKT3_IT_OPCODE_S(op) | PKT_COUNT_S(count)) +#define PKT3(op, count, predicate) (PKT_TYPE_S(3) | PKT3_IT_OPCODE_S(op) | PKT_COUNT_S(count) | PKT3_PRED_S(predicate)) /* Registers */ #define R_0280A0_CB_COLOR0_INFO 0x0280A0 diff --git a/src/gallium/winsys/r600/drm/radeon_bo.c b/src/gallium/winsys/r600/drm/radeon_bo.c index 557cfb9597..ba02a3c2bd 100644 --- a/src/gallium/winsys/r600/drm/radeon_bo.c +++ b/src/gallium/winsys/r600/drm/radeon_bo.c @@ -33,6 +33,25 @@ #include "xf86drm.h" #include "radeon_drm.h" +#ifdef ANDROID + +extern void* __mmap2(void*, size_t, int, int, int, size_t); + +#define MMAP2_SHIFT 12 +static void* android_mmap2(void *addr, size_t size, int prot, int flags, int fd, unsigned long long offset) +{ + if ( offset & ((1UL << MMAP2_SHIFT)-1) ) { + errno = EINVAL; + return MAP_FAILED; + } + + return __mmap2(addr, size, prot, flags, fd, (size_t)(offset >> MMAP2_SHIFT)); +} + +#define mmap(addr, size, prot, flags, fd, offset) android_mmap2(addr, size, prot, flags, fd, offset) + +#endif /* ANDROID */ + static int radeon_bo_fixed_map(struct radeon *radeon, struct radeon_bo *bo) { struct drm_radeon_gem_mmap args; @@ -98,7 +117,7 @@ struct radeon_bo *radeon_bo(struct radeon *radeon, unsigned handle, bo->size = open_arg.size; bo->shared = TRUE; } else { - struct drm_radeon_gem_create args; + struct drm_radeon_gem_create args = {}; args.size = size; args.alignment = alignment; @@ -156,7 +175,7 @@ int radeon_bo_wait(struct radeon *radeon, struct radeon_bo *bo) if (!bo->shared) { if (!bo->fence) return 0; - if (bo->fence <= *bo->ctx->cfence) { + if (bo->fence <= *radeon->cfence) { LIST_DELINIT(&bo->fencedlist); bo->fence = 0; return 0; @@ -181,7 +200,7 @@ int radeon_bo_busy(struct radeon *radeon, struct radeon_bo *bo, uint32_t *domain if (!bo->shared) { if (!bo->fence) return 0; - if (bo->fence <= *bo->ctx->cfence) { + if (bo->fence <= *radeon->cfence) { LIST_DELINIT(&bo->fencedlist); bo->fence = 0; return 0; @@ -204,15 +223,15 @@ int radeon_bo_get_tiling_flags(struct radeon *radeon, uint32_t *tiling_flags, uint32_t *pitch) { - struct drm_radeon_gem_get_tiling args; + struct drm_radeon_gem_get_tiling args = {}; int ret; - + args.handle = bo->handle; ret = drmCommandWriteRead(radeon->fd, DRM_RADEON_GEM_GET_TILING, &args, sizeof(args)); if (ret) return ret; - + *tiling_flags = args.tiling_flags; *pitch = args.pitch; return ret; diff --git a/src/gallium/winsys/r600/drm/radeon_bo_pb.c b/src/gallium/winsys/r600/drm/radeon_bo_pb.c deleted file mode 100644 index 4bd3ae3ca1..0000000000 --- a/src/gallium/winsys/r600/drm/radeon_bo_pb.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2010 Dave Airlie - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Dave Airlie - */ -#include <util/u_inlines.h> -#include <util/u_memory.h> -#include <util/u_double_list.h> -#include <pipebuffer/pb_buffer.h> -#include <pipebuffer/pb_bufmgr.h> -#include "r600_priv.h" - -struct radeon_bo_pb { - struct pb_buffer b; - struct radeon_bo *bo; - - struct radeon_bo_pbmgr *mgr; -}; - -extern const struct pb_vtbl radeon_bo_pb_vtbl; - -static INLINE struct radeon_bo_pb *radeon_bo_pb(struct pb_buffer *buf) -{ - assert(buf); - assert(buf->vtbl == &radeon_bo_pb_vtbl); - return (struct radeon_bo_pb *)buf; -} - -struct radeon_bo_pbmgr { - struct pb_manager b; - struct radeon *radeon; -}; - -static INLINE struct radeon_bo_pbmgr *radeon_bo_pbmgr(struct pb_manager *mgr) -{ - assert(mgr); - return (struct radeon_bo_pbmgr *)mgr; -} - -static void radeon_bo_pb_destroy(struct pb_buffer *_buf) -{ - struct radeon_bo_pb *buf = radeon_bo_pb(_buf); - - /* If this buffer is on the list of buffers to unmap, - * do the unmapping now. - */ - radeon_bo_unmap(buf->mgr->radeon, buf->bo); - radeon_bo_reference(buf->mgr->radeon, &buf->bo, NULL); - FREE(buf); -} - -static void * -radeon_bo_pb_map_internal(struct pb_buffer *_buf, - unsigned flags, void *ctx) -{ - struct radeon_bo_pb *buf = radeon_bo_pb(_buf); - struct pipe_context *pctx = ctx; - - if (flags & PB_USAGE_UNSYNCHRONIZED) { - if (radeon_bo_map(buf->mgr->radeon, buf->bo)) { - return NULL; - } - return buf->bo->data; - } - - if (p_atomic_read(&buf->bo->reference.count) > 1) { - if (flags & PB_USAGE_DONTBLOCK) { - return NULL; - } - if (ctx) { - pctx->flush(pctx, 0, NULL); - } - } - - if (flags & PB_USAGE_DONTBLOCK) { - uint32_t domain; - if (radeon_bo_busy(buf->mgr->radeon, buf->bo, &domain)) - return NULL; - if (radeon_bo_map(buf->mgr->radeon, buf->bo)) { - return NULL; - } - goto out; - } - - if (radeon_bo_map(buf->mgr->radeon, buf->bo)) { - return NULL; - } - if (radeon_bo_wait(buf->mgr->radeon, buf->bo)) { - radeon_bo_unmap(buf->mgr->radeon, buf->bo); - return NULL; - } -out: - return buf->bo->data; -} - -static void radeon_bo_pb_unmap_internal(struct pb_buffer *_buf) -{ -} - -static void -radeon_bo_pb_get_base_buffer(struct pb_buffer *buf, - struct pb_buffer **base_buf, - unsigned *offset) -{ - *base_buf = buf; - *offset = 0; -} - -static enum pipe_error -radeon_bo_pb_validate(struct pb_buffer *_buf, - struct pb_validate *vl, - unsigned flags) -{ - /* Always pinned */ - return PIPE_OK; -} - -static void -radeon_bo_pb_fence(struct pb_buffer *buf, - struct pipe_fence_handle *fence) -{ -} - -const struct pb_vtbl radeon_bo_pb_vtbl = { - radeon_bo_pb_destroy, - radeon_bo_pb_map_internal, - radeon_bo_pb_unmap_internal, - radeon_bo_pb_validate, - radeon_bo_pb_fence, - radeon_bo_pb_get_base_buffer, -}; - -struct pb_buffer * -radeon_bo_pb_create_buffer_from_handle(struct pb_manager *_mgr, - uint32_t handle) -{ - struct radeon_bo_pbmgr *mgr = radeon_bo_pbmgr(_mgr); - struct radeon *radeon = mgr->radeon; - struct radeon_bo_pb *bo; - struct radeon_bo *hw_bo; - - hw_bo = radeon_bo(radeon, handle, 0, 0); - if (hw_bo == NULL) - return NULL; - - bo = CALLOC_STRUCT(radeon_bo_pb); - if (!bo) { - radeon_bo_reference(radeon, &hw_bo, NULL); - return NULL; - } - - pipe_reference_init(&bo->b.base.reference, 1); - bo->b.base.alignment = 0; - bo->b.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ; - bo->b.base.size = hw_bo->size; - bo->b.vtbl = &radeon_bo_pb_vtbl; - bo->mgr = mgr; - - bo->bo = hw_bo; - - return &bo->b; -} - -static struct pb_buffer * -radeon_bo_pb_create_buffer(struct pb_manager *_mgr, - pb_size size, - const struct pb_desc *desc) -{ - struct radeon_bo_pbmgr *mgr = radeon_bo_pbmgr(_mgr); - struct radeon *radeon = mgr->radeon; - struct radeon_bo_pb *bo; - - bo = CALLOC_STRUCT(radeon_bo_pb); - if (!bo) - goto error1; - - pipe_reference_init(&bo->b.base.reference, 1); - bo->b.base.alignment = desc->alignment; - bo->b.base.usage = desc->usage; - bo->b.base.size = size; - bo->b.vtbl = &radeon_bo_pb_vtbl; - bo->mgr = mgr; - - bo->bo = radeon_bo(radeon, 0, size, desc->alignment); - if (bo->bo == NULL) - goto error2; - return &bo->b; - -error2: - FREE(bo); -error1: - return NULL; -} - -static void -radeon_bo_pbmgr_flush(struct pb_manager *mgr) -{ - /* NOP */ -} - -static void -radeon_bo_pbmgr_destroy(struct pb_manager *_mgr) -{ - struct radeon_bo_pbmgr *mgr = radeon_bo_pbmgr(_mgr); - FREE(mgr); -} - -struct pb_manager *radeon_bo_pbmgr_create(struct radeon *radeon) -{ - struct radeon_bo_pbmgr *mgr; - - mgr = CALLOC_STRUCT(radeon_bo_pbmgr); - if (!mgr) - return NULL; - - mgr->b.destroy = radeon_bo_pbmgr_destroy; - mgr->b.create_buffer = radeon_bo_pb_create_buffer; - mgr->b.flush = radeon_bo_pbmgr_flush; - - mgr->radeon = radeon; - return &mgr->b; -} - -struct radeon_bo *radeon_bo_pb_get_bo(struct pb_buffer *_buf) -{ - struct radeon_bo_pb *buf; - if (_buf->vtbl == &radeon_bo_pb_vtbl) { - buf = radeon_bo_pb(_buf); - return buf->bo; - } else { - struct pb_buffer *base_buf; - pb_size offset; - pb_get_base_buffer(_buf, &base_buf, &offset); - if (base_buf->vtbl == &radeon_bo_pb_vtbl) { - buf = radeon_bo_pb(base_buf); - return buf->bo; - } - } - return NULL; -} diff --git a/src/gallium/winsys/r600/drm/radeon_pciid.c b/src/gallium/winsys/r600/drm/radeon_pciid.c index 92560a488a..f19956931d 100644 --- a/src/gallium/winsys/r600/drm/radeon_pciid.c +++ b/src/gallium/winsys/r600/drm/radeon_pciid.c @@ -32,7 +32,7 @@ struct pci_id { unsigned family; }; -struct pci_id radeon_pci_id[] = { +static const struct pci_id radeon_pci_id[] = { {0x1002, 0x3150, CHIP_RV380}, {0x1002, 0x3152, CHIP_RV380}, {0x1002, 0x3154, CHIP_RV380}, @@ -40,29 +40,29 @@ struct pci_id radeon_pci_id[] = { {0x1002, 0x3E54, CHIP_RV380}, {0x1002, 0x4136, CHIP_RS100}, {0x1002, 0x4137, CHIP_RS200}, - {0x1002, 0x4144, CHIP_R300}, - {0x1002, 0x4145, CHIP_R300}, - {0x1002, 0x4146, CHIP_R300}, - {0x1002, 0x4147, CHIP_R300}, - {0x1002, 0x4148, CHIP_R350}, - {0x1002, 0x4149, CHIP_R350}, - {0x1002, 0x414A, CHIP_R350}, - {0x1002, 0x414B, CHIP_R350}, - {0x1002, 0x4150, CHIP_RV350}, - {0x1002, 0x4151, CHIP_RV350}, - {0x1002, 0x4152, CHIP_RV350}, - {0x1002, 0x4153, CHIP_RV350}, - {0x1002, 0x4154, CHIP_RV350}, - {0x1002, 0x4155, CHIP_RV350}, - {0x1002, 0x4156, CHIP_RV350}, + {0x1002, 0x4144, CHIP_R300}, + {0x1002, 0x4145, CHIP_R300}, + {0x1002, 0x4146, CHIP_R300}, + {0x1002, 0x4147, CHIP_R300}, + {0x1002, 0x4148, CHIP_R350}, + {0x1002, 0x4149, CHIP_R350}, + {0x1002, 0x414A, CHIP_R350}, + {0x1002, 0x414B, CHIP_R350}, + {0x1002, 0x4150, CHIP_RV350}, + {0x1002, 0x4151, CHIP_RV350}, + {0x1002, 0x4152, CHIP_RV350}, + {0x1002, 0x4153, CHIP_RV350}, + {0x1002, 0x4154, CHIP_RV350}, + {0x1002, 0x4155, CHIP_RV350}, + {0x1002, 0x4156, CHIP_RV350}, {0x1002, 0x4237, CHIP_RS200}, - {0x1002, 0x4242, CHIP_R200}, - {0x1002, 0x4243, CHIP_R200}, + {0x1002, 0x4242, CHIP_R200}, + {0x1002, 0x4243, CHIP_R200}, {0x1002, 0x4336, CHIP_RS100}, {0x1002, 0x4337, CHIP_RS200}, {0x1002, 0x4437, CHIP_RS200}, - {0x1002, 0x4966, CHIP_RV250}, - {0x1002, 0x4967, CHIP_RV250}, + {0x1002, 0x4966, CHIP_RV250}, + {0x1002, 0x4967, CHIP_RV250}, {0x1002, 0x4A48, CHIP_R420}, {0x1002, 0x4A49, CHIP_R420}, {0x1002, 0x4A4A, CHIP_R420}, @@ -85,14 +85,14 @@ struct pci_id radeon_pci_id[] = { {0x1002, 0x4C64, CHIP_RV250}, {0x1002, 0x4C66, CHIP_RV250}, {0x1002, 0x4C67, CHIP_RV250}, - {0x1002, 0x4E44, CHIP_R300}, - {0x1002, 0x4E45, CHIP_R300}, - {0x1002, 0x4E46, CHIP_R300}, - {0x1002, 0x4E47, CHIP_R300}, - {0x1002, 0x4E48, CHIP_R350}, - {0x1002, 0x4E49, CHIP_R350}, - {0x1002, 0x4E4A, CHIP_R350}, - {0x1002, 0x4E4B, CHIP_R350}, + {0x1002, 0x4E44, CHIP_R300}, + {0x1002, 0x4E45, CHIP_R300}, + {0x1002, 0x4E46, CHIP_R300}, + {0x1002, 0x4E47, CHIP_R300}, + {0x1002, 0x4E48, CHIP_R350}, + {0x1002, 0x4E49, CHIP_R350}, + {0x1002, 0x4E4A, CHIP_R350}, + {0x1002, 0x4E4B, CHIP_R350}, {0x1002, 0x4E50, CHIP_RV350}, {0x1002, 0x4E51, CHIP_RV350}, {0x1002, 0x4E52, CHIP_RV350}, @@ -103,13 +103,13 @@ struct pci_id radeon_pci_id[] = { {0x1002, 0x5145, CHIP_R100}, {0x1002, 0x5146, CHIP_R100}, {0x1002, 0x5147, CHIP_R100}, - {0x1002, 0x5148, CHIP_R200}, - {0x1002, 0x514C, CHIP_R200}, - {0x1002, 0x514D, CHIP_R200}, - {0x1002, 0x5157, CHIP_RV200}, - {0x1002, 0x5158, CHIP_RV200}, - {0x1002, 0x5159, CHIP_RV100}, - {0x1002, 0x515A, CHIP_RV100}, + {0x1002, 0x5148, CHIP_R200}, + {0x1002, 0x514C, CHIP_R200}, + {0x1002, 0x514D, CHIP_R200}, + {0x1002, 0x5157, CHIP_RV200}, + {0x1002, 0x5158, CHIP_RV200}, + {0x1002, 0x5159, CHIP_RV100}, + {0x1002, 0x515A, CHIP_RV100}, {0x1002, 0x515E, CHIP_RV100}, {0x1002, 0x5460, CHIP_RV380}, {0x1002, 0x5462, CHIP_RV380}, @@ -138,10 +138,10 @@ struct pci_id radeon_pci_id[] = { {0x1002, 0x5955, CHIP_RS480}, {0x1002, 0x5974, CHIP_RS480}, {0x1002, 0x5975, CHIP_RS480}, - {0x1002, 0x5960, CHIP_RV280}, - {0x1002, 0x5961, CHIP_RV280}, - {0x1002, 0x5962, CHIP_RV280}, - {0x1002, 0x5964, CHIP_RV280}, + {0x1002, 0x5960, CHIP_RV280}, + {0x1002, 0x5961, CHIP_RV280}, + {0x1002, 0x5962, CHIP_RV280}, + {0x1002, 0x5964, CHIP_RV280}, {0x1002, 0x5965, CHIP_RV280}, {0x1002, 0x5969, CHIP_RV100}, {0x1002, 0x5a41, CHIP_RS400}, @@ -445,6 +445,42 @@ struct pci_id radeon_pci_id[] = { {0x1002, 0x9803, CHIP_PALM}, {0x1002, 0x9804, CHIP_PALM}, {0x1002, 0x9805, CHIP_PALM}, + {0x1002, 0x6720, CHIP_BARTS}, + {0x1002, 0x6721, CHIP_BARTS}, + {0x1002, 0x6722, CHIP_BARTS}, + {0x1002, 0x6723, CHIP_BARTS}, + {0x1002, 0x6724, CHIP_BARTS}, + {0x1002, 0x6725, CHIP_BARTS}, + {0x1002, 0x6726, CHIP_BARTS}, + {0x1002, 0x6727, CHIP_BARTS}, + {0x1002, 0x6728, CHIP_BARTS}, + {0x1002, 0x6729, CHIP_BARTS}, + {0x1002, 0x6738, CHIP_BARTS}, + {0x1002, 0x6739, CHIP_BARTS}, + {0x1002, 0x6740, CHIP_TURKS}, + {0x1002, 0x6741, CHIP_TURKS}, + {0x1002, 0x6742, CHIP_TURKS}, + {0x1002, 0x6743, CHIP_TURKS}, + {0x1002, 0x6744, CHIP_TURKS}, + {0x1002, 0x6745, CHIP_TURKS}, + {0x1002, 0x6746, CHIP_TURKS}, + {0x1002, 0x6747, CHIP_TURKS}, + {0x1002, 0x6748, CHIP_TURKS}, + {0x1002, 0x6749, CHIP_TURKS}, + {0x1002, 0x6750, CHIP_TURKS}, + {0x1002, 0x6758, CHIP_TURKS}, + {0x1002, 0x6759, CHIP_TURKS}, + {0x1002, 0x6760, CHIP_CAICOS}, + {0x1002, 0x6761, CHIP_CAICOS}, + {0x1002, 0x6762, CHIP_CAICOS}, + {0x1002, 0x6763, CHIP_CAICOS}, + {0x1002, 0x6764, CHIP_CAICOS}, + {0x1002, 0x6765, CHIP_CAICOS}, + {0x1002, 0x6766, CHIP_CAICOS}, + {0x1002, 0x6767, CHIP_CAICOS}, + {0x1002, 0x6768, CHIP_CAICOS}, + {0x1002, 0x6770, CHIP_CAICOS}, + {0x1002, 0x6779, CHIP_CAICOS}, {0, 0}, }; diff --git a/src/gallium/winsys/radeon/drm/Makefile b/src/gallium/winsys/radeon/drm/Makefile index aa73edde34..e63ae6f500 100644 --- a/src/gallium/winsys/radeon/drm/Makefile +++ b/src/gallium/winsys/radeon/drm/Makefile @@ -5,9 +5,9 @@ include $(TOP)/configs/current LIBNAME = radeonwinsys C_SOURCES = \ - radeon_drm_buffer.c \ - radeon_drm_common.c \ - radeon_r300.c + radeon_drm_bo.c \ + radeon_drm_cs.c \ + radeon_drm_common.c LIBRARY_INCLUDES = -I$(TOP)/src/gallium/drivers/r300 \ $(shell pkg-config libdrm --cflags-only-I) diff --git a/src/gallium/winsys/radeon/drm/SConscript b/src/gallium/winsys/radeon/drm/SConscript index 2dbf61a7ba..b16e03556d 100644 --- a/src/gallium/winsys/radeon/drm/SConscript +++ b/src/gallium/winsys/radeon/drm/SConscript @@ -3,12 +3,17 @@ Import('*') env = env.Clone() radeon_sources = [ - 'radeon_drm_buffer.c', + 'radeon_drm_bo.c', + 'radeon_drm_cs.c', 'radeon_drm_common.c', - 'radeon_r300.c', ] -env.ParseConfig('pkg-config --cflags libdrm_radeon') +try: + env.ParseConfig('pkg-config --cflags libdrm_radeon') +except: + print 'warning: not building r300g' + Return() + env.Append(CPPPATH = '#/src/gallium/drivers/r300') radeonwinsys = env.ConvenienceLibrary( diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c new file mode 100644 index 0000000000..9eb833454d --- /dev/null +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -0,0 +1,602 @@ +/* + * Copyright © 2011 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + +#define _FILE_OFFSET_BITS 64 +#include "radeon_drm_cs.h" + +#include "util/u_hash_table.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" +#include "os/os_thread.h" + +#include "state_tracker/drm_driver.h" + +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <xf86drm.h> +#include <errno.h> + +#define RADEON_BO_FLAGS_MACRO_TILE 1 +#define RADEON_BO_FLAGS_MICRO_TILE 2 +#define RADEON_BO_FLAGS_MICRO_TILE_SQUARE 0x20 + +extern const struct pb_vtbl radeon_bo_vtbl; + + +static INLINE struct radeon_bo *radeon_bo(struct pb_buffer *bo) +{ + assert(bo->vtbl == &radeon_bo_vtbl); + return (struct radeon_bo *)bo; +} + +struct radeon_bomgr { + /* Base class. */ + struct pb_manager base; + + /* Winsys. */ + struct radeon_drm_winsys *rws; + + /* List of buffer handles and its mutex. */ + struct util_hash_table *bo_handles; + pipe_mutex bo_handles_mutex; +}; + +static INLINE struct radeon_bomgr *radeon_bomgr(struct pb_manager *mgr) +{ + return (struct radeon_bomgr *)mgr; +} + +static struct radeon_bo *get_radeon_bo(struct pb_buffer *_buf) +{ + struct radeon_bo *bo = NULL; + + if (_buf->vtbl == &radeon_bo_vtbl) { + bo = radeon_bo(_buf); + } else { + struct pb_buffer *base_buf; + pb_size offset; + pb_get_base_buffer(_buf, &base_buf, &offset); + + if (base_buf->vtbl == &radeon_bo_vtbl) + bo = radeon_bo(base_buf); + } + + return bo; +} + +void radeon_bo_unref(struct radeon_bo *bo) +{ + struct drm_gem_close args = {}; + + if (!p_atomic_dec_zero(&bo->ref_count)) + return; + + if (bo->name) { + pipe_mutex_lock(bo->mgr->bo_handles_mutex); + util_hash_table_remove(bo->mgr->bo_handles, + (void*)(uintptr_t)bo->name); + pipe_mutex_unlock(bo->mgr->bo_handles_mutex); + } + + if (bo->ptr) + munmap(bo->ptr, bo->size); + + /* Close object. */ + args.handle = bo->handle; + drmIoctl(bo->rws->fd, DRM_IOCTL_GEM_CLOSE, &args); + pipe_mutex_destroy(bo->map_mutex); + FREE(bo); +} + +static void radeon_bo_wait(struct r300_winsys_bo *_buf) +{ + struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf)); + struct drm_radeon_gem_wait_idle args = {}; + + while (p_atomic_read(&bo->num_active_ioctls)) { + sched_yield(); + } + + args.handle = bo->handle; + while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE, + &args, sizeof(args)) == -EBUSY); +} + +static boolean radeon_bo_is_busy(struct r300_winsys_bo *_buf) +{ + struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf)); + struct drm_radeon_gem_busy args = {}; + + if (p_atomic_read(&bo->num_active_ioctls)) { + return TRUE; + } + + args.handle = bo->handle; + return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY, + &args, sizeof(args)) != 0; +} + +static void radeon_bo_destroy(struct pb_buffer *_buf) +{ + struct radeon_bo *bo = radeon_bo(_buf); + + radeon_bo_unref(bo); +} + +static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage) +{ + unsigned res = 0; + + if (usage & PIPE_TRANSFER_DONTBLOCK) + res |= PB_USAGE_DONTBLOCK; + + if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) + res |= PB_USAGE_UNSYNCHRONIZED; + + return res; +} + +static void *radeon_bo_map_internal(struct pb_buffer *_buf, + unsigned flags, void *flush_ctx) +{ + struct radeon_bo *bo = radeon_bo(_buf); + struct radeon_drm_cs *cs = flush_ctx; + struct drm_radeon_gem_mmap args = {}; + void *ptr; + + /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */ + if (!(flags & PB_USAGE_UNSYNCHRONIZED)) { + /* DONTBLOCK doesn't make sense with UNSYNCHRONIZED. */ + if (flags & PB_USAGE_DONTBLOCK) { + if (radeon_bo_is_referenced_by_cs(cs, bo)) { + cs->flush_cs(cs->flush_data, R300_FLUSH_ASYNC); + return NULL; + } + + if (radeon_bo_is_busy((struct r300_winsys_bo*)bo)) { + return NULL; + } + } else { + if (radeon_bo_is_referenced_by_cs(cs, bo)) { + cs->flush_cs(cs->flush_data, 0); + } else { + /* Try to avoid busy-waiting in radeon_bo_wait. */ + if (p_atomic_read(&bo->num_active_ioctls)) + radeon_drm_cs_sync_flush(cs); + } + + radeon_bo_wait((struct r300_winsys_bo*)bo); + } + } + + /* Return the pointer if it's already mapped. */ + if (bo->ptr) + return bo->ptr; + + /* Map the buffer. */ + pipe_mutex_lock(bo->map_mutex); + args.handle = bo->handle; + args.offset = 0; + args.size = (uint64_t)bo->size; + if (drmCommandWriteRead(bo->rws->fd, + DRM_RADEON_GEM_MMAP, + &args, + sizeof(args))) { + pipe_mutex_unlock(bo->map_mutex); + fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n", + bo, bo->handle); + return NULL; + } + + ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, + bo->rws->fd, args.addr_ptr); + if (ptr == MAP_FAILED) { + pipe_mutex_unlock(bo->map_mutex); + fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno); + return NULL; + } + bo->ptr = ptr; + pipe_mutex_unlock(bo->map_mutex); + + return bo->ptr; +} + +static void radeon_bo_unmap_internal(struct pb_buffer *_buf) +{ + /* NOP */ +} + +static void radeon_bo_get_base_buffer(struct pb_buffer *buf, + struct pb_buffer **base_buf, + unsigned *offset) +{ + *base_buf = buf; + *offset = 0; +} + +static enum pipe_error radeon_bo_validate(struct pb_buffer *_buf, + struct pb_validate *vl, + unsigned flags) +{ + /* Always pinned */ + return PIPE_OK; +} + +static void radeon_bo_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ +} + +const struct pb_vtbl radeon_bo_vtbl = { + radeon_bo_destroy, + radeon_bo_map_internal, + radeon_bo_unmap_internal, + radeon_bo_validate, + radeon_bo_fence, + radeon_bo_get_base_buffer, +}; + +static struct pb_buffer *radeon_bomgr_create_bo(struct pb_manager *_mgr, + pb_size size, + const struct pb_desc *desc) +{ + struct radeon_bomgr *mgr = radeon_bomgr(_mgr); + struct radeon_drm_winsys *rws = mgr->rws; + struct radeon_bo *bo; + struct drm_radeon_gem_create args = {}; + + args.size = size; + args.alignment = desc->alignment; + args.initial_domain = + (desc->usage & RADEON_PB_USAGE_DOMAIN_GTT ? + RADEON_GEM_DOMAIN_GTT : 0) | + (desc->usage & RADEON_PB_USAGE_DOMAIN_VRAM ? + RADEON_GEM_DOMAIN_VRAM : 0); + + if (drmCommandWriteRead(rws->fd, DRM_RADEON_GEM_CREATE, + &args, sizeof(args))) { + fprintf(stderr, "Failed to allocate :\n"); + fprintf(stderr, " size : %d bytes\n", size); + fprintf(stderr, " alignment : %d bytes\n", desc->alignment); + fprintf(stderr, " domains : %d\n", args.initial_domain); + return NULL; + } + + bo = CALLOC_STRUCT(radeon_bo); + if (!bo) + return NULL; + + pipe_reference_init(&bo->base.base.reference, 1); + bo->base.base.alignment = desc->alignment; + bo->base.base.usage = desc->usage; + bo->base.base.size = size; + bo->base.vtbl = &radeon_bo_vtbl; + bo->mgr = mgr; + bo->rws = mgr->rws; + bo->handle = args.handle; + bo->size = size; + pipe_mutex_init(bo->map_mutex); + + radeon_bo_ref(bo); + return &bo->base; +} + +static void radeon_bomgr_flush(struct pb_manager *mgr) +{ + /* NOP */ +} + +/* This is for the cache bufmgr. */ +static boolean radeon_bomgr_is_buffer_busy(struct pb_manager *_mgr, + struct pb_buffer *_buf) +{ + struct radeon_bo *bo = radeon_bo(_buf); + + if (radeon_bo_is_referenced_by_any_cs(bo)) { + return TRUE; + } + + if (radeon_bo_is_busy((struct r300_winsys_bo*)bo)) { + return TRUE; + } + + return FALSE; +} + +static void radeon_bomgr_destroy(struct pb_manager *_mgr) +{ + struct radeon_bomgr *mgr = radeon_bomgr(_mgr); + util_hash_table_destroy(mgr->bo_handles); + pipe_mutex_destroy(mgr->bo_handles_mutex); + FREE(mgr); +} + +#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) + +static unsigned handle_hash(void *key) +{ + return PTR_TO_UINT(key); +} + +static int handle_compare(void *key1, void *key2) +{ + return PTR_TO_UINT(key1) != PTR_TO_UINT(key2); +} + +struct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws) +{ + struct radeon_bomgr *mgr; + + mgr = CALLOC_STRUCT(radeon_bomgr); + if (!mgr) + return NULL; + + mgr->base.destroy = radeon_bomgr_destroy; + mgr->base.create_buffer = radeon_bomgr_create_bo; + mgr->base.flush = radeon_bomgr_flush; + mgr->base.is_buffer_busy = radeon_bomgr_is_buffer_busy; + + mgr->rws = rws; + mgr->bo_handles = util_hash_table_create(handle_hash, handle_compare); + pipe_mutex_init(mgr->bo_handles_mutex); + return &mgr->base; +} + +static void *radeon_bo_map(struct r300_winsys_bo *buf, + struct r300_winsys_cs *cs, + enum pipe_transfer_usage usage) +{ + struct pb_buffer *_buf = pb_buffer(buf); + + return pb_map(_buf, get_pb_usage_from_transfer_flags(usage), cs); +} + +static void radeon_bo_get_tiling(struct r300_winsys_bo *_buf, + enum r300_buffer_tiling *microtiled, + enum r300_buffer_tiling *macrotiled) +{ + struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf)); + struct drm_radeon_gem_set_tiling args = {}; + + args.handle = bo->handle; + + drmCommandWriteRead(bo->rws->fd, + DRM_RADEON_GEM_GET_TILING, + &args, + sizeof(args)); + + *microtiled = R300_BUFFER_LINEAR; + *macrotiled = R300_BUFFER_LINEAR; + if (args.tiling_flags & RADEON_BO_FLAGS_MICRO_TILE) + *microtiled = R300_BUFFER_TILED; + + if (args.tiling_flags & RADEON_BO_FLAGS_MACRO_TILE) + *macrotiled = R300_BUFFER_TILED; +} + +static void radeon_bo_set_tiling(struct r300_winsys_bo *_buf, + struct r300_winsys_cs *rcs, + enum r300_buffer_tiling microtiled, + enum r300_buffer_tiling macrotiled, + uint32_t pitch) +{ + struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf)); + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + struct drm_radeon_gem_set_tiling args = {}; + + /* Tiling determines how DRM treats the buffer data. + * We must flush CS when changing it if the buffer is referenced. */ + if (cs && radeon_bo_is_referenced_by_cs(cs, bo)) { + cs->flush_cs(cs->flush_data, 0); + } + + while (p_atomic_read(&bo->num_active_ioctls)) { + sched_yield(); + } + + if (microtiled == R300_BUFFER_TILED) + args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE; + else if (microtiled == R300_BUFFER_SQUARETILED) + args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE; + + if (macrotiled == R300_BUFFER_TILED) + args.tiling_flags |= RADEON_BO_FLAGS_MACRO_TILE; + + args.handle = bo->handle; + args.pitch = pitch; + + drmCommandWriteRead(bo->rws->fd, + DRM_RADEON_GEM_SET_TILING, + &args, + sizeof(args)); +} + +static struct r300_winsys_cs_handle *radeon_drm_get_cs_handle( + struct r300_winsys_bo *_buf) +{ + /* return radeon_bo. */ + return (struct r300_winsys_cs_handle*) + get_radeon_bo(pb_buffer(_buf)); +} + +static unsigned get_pb_usage_from_create_flags(unsigned bind, unsigned usage, + enum r300_buffer_domain domain) +{ + unsigned res = 0; + + if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) + res |= RADEON_PB_USAGE_CACHE; + + if (domain & R300_DOMAIN_GTT) + res |= RADEON_PB_USAGE_DOMAIN_GTT; + + if (domain & R300_DOMAIN_VRAM) + res |= RADEON_PB_USAGE_DOMAIN_VRAM; + + return res; +} + +static struct r300_winsys_bo * +radeon_winsys_bo_create(struct r300_winsys_screen *rws, + unsigned size, + unsigned alignment, + unsigned bind, + unsigned usage, + enum r300_buffer_domain domain) +{ + struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); + struct pb_desc desc; + struct pb_manager *provider; + struct pb_buffer *buffer; + + memset(&desc, 0, sizeof(desc)); + desc.alignment = alignment; + desc.usage = get_pb_usage_from_create_flags(bind, usage, domain); + + /* Assign a buffer manager. */ + if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) + provider = ws->cman; + else + provider = ws->kman; + + buffer = provider->create_buffer(provider, size, &desc); + if (!buffer) + return NULL; + + return (struct r300_winsys_bo*)buffer; +} + +static struct r300_winsys_bo *radeon_winsys_bo_from_handle(struct r300_winsys_screen *rws, + struct winsys_handle *whandle, + unsigned *stride, + unsigned *size) +{ + struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); + struct radeon_bo *bo; + struct radeon_bomgr *mgr = radeon_bomgr(ws->kman); + struct drm_gem_open open_arg = {}; + + /* We must maintain a list of pairs <handle, bo>, so that we always return + * the same BO for one particular handle. If we didn't do that and created + * more than one BO for the same handle and then relocated them in a CS, + * we would hit a deadlock in the kernel. + * + * The list of pairs is guarded by a mutex, of course. */ + pipe_mutex_lock(mgr->bo_handles_mutex); + + /* First check if there already is an existing bo for the handle. */ + bo = util_hash_table_get(mgr->bo_handles, (void*)(uintptr_t)whandle->handle); + if (bo) { + /* Increase the refcount. */ + struct pb_buffer *b = NULL; + pb_reference(&b, &bo->base); + goto done; + } + + /* There isn't, create a new one. */ + bo = CALLOC_STRUCT(radeon_bo); + if (!bo) { + goto fail; + } + + /* Open the BO. */ + open_arg.name = whandle->handle; + if (drmIoctl(ws->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) { + FREE(bo); + goto fail; + } + bo->handle = open_arg.handle; + bo->size = open_arg.size; + bo->name = whandle->handle; + radeon_bo_ref(bo); + + /* Initialize it. */ + pipe_reference_init(&bo->base.base.reference, 1); + bo->base.base.alignment = 0; + bo->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ; + bo->base.base.size = bo->size; + bo->base.vtbl = &radeon_bo_vtbl; + bo->mgr = mgr; + bo->rws = mgr->rws; + pipe_mutex_init(bo->map_mutex); + + util_hash_table_set(mgr->bo_handles, (void*)(uintptr_t)whandle->handle, bo); + +done: + pipe_mutex_unlock(mgr->bo_handles_mutex); + + if (stride) + *stride = whandle->stride; + if (size) + *size = bo->base.base.size; + + return (struct r300_winsys_bo*)bo; + +fail: + pipe_mutex_unlock(mgr->bo_handles_mutex); + return NULL; +} + +static boolean radeon_winsys_bo_get_handle(struct r300_winsys_bo *buffer, + unsigned stride, + struct winsys_handle *whandle) +{ + struct drm_gem_flink flink = {}; + struct radeon_bo *bo = get_radeon_bo(pb_buffer(buffer)); + + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + if (!bo->flinked) { + flink.handle = bo->handle; + + if (ioctl(bo->rws->fd, DRM_IOCTL_GEM_FLINK, &flink)) { + return FALSE; + } + + bo->flinked = TRUE; + bo->flink = flink.name; + } + whandle->handle = bo->flink; + } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { + whandle->handle = bo->handle; + } + + whandle->stride = stride; + return TRUE; +} + +void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws) +{ + ws->base.buffer_get_cs_handle = radeon_drm_get_cs_handle; + ws->base.buffer_set_tiling = radeon_bo_set_tiling; + ws->base.buffer_get_tiling = radeon_bo_get_tiling; + ws->base.buffer_map = radeon_bo_map; + ws->base.buffer_unmap = pb_unmap; + ws->base.buffer_wait = radeon_bo_wait; + ws->base.buffer_is_busy = radeon_bo_is_busy; + ws->base.buffer_create = radeon_winsys_bo_create; + ws->base.buffer_from_handle = radeon_winsys_bo_from_handle; + ws->base.buffer_get_handle = radeon_winsys_bo_get_handle; +} diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.h b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h index 494abdc0b4..a26866b7e7 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h @@ -1,5 +1,6 @@ /* * Copyright © 2008 Jérôme Glisse + * Copyright © 2011 Marek Olšák <maraeo@gmail.com> * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining @@ -26,28 +27,61 @@ /* * Authors: * Jérôme Glisse <glisse@freedesktop.org> + * Marek Olšák <maraeo@gmail.com> */ #ifndef RADEON_DRM_BUFFER_H #define RADEON_DRM_BUFFER_H #include "radeon_winsys.h" +#include "pipebuffer/pb_bufmgr.h" +#include "os/os_thread.h" -#define RADEON_PB_USAGE_VERTEX (1 << 28) +#define RADEON_PB_USAGE_CACHE (1 << 28) #define RADEON_PB_USAGE_DOMAIN_GTT (1 << 29) #define RADEON_PB_USAGE_DOMAIN_VRAM (1 << 30) +struct radeon_bomgr; + +struct radeon_bo { + struct pb_buffer base; + struct radeon_bomgr *mgr; + struct radeon_drm_winsys *rws; + + void *ptr; + pipe_mutex map_mutex; + + uint32_t size; + uint32_t handle; + uint32_t name; + + int ref_count; + + /* how many command streams is this bo referenced in? */ + int num_cs_references; + + /* how many command streams, which are being emitted in a separate + * thread, is this bo referenced in? */ + int num_active_ioctls; + + boolean flinked; + uint32_t flink; +}; + +struct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws); +void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws); + +void radeon_bo_unref(struct radeon_bo *buf); + + +static INLINE void radeon_bo_ref(struct radeon_bo *bo) +{ + p_atomic_inc(&bo->ref_count); +} + static INLINE struct pb_buffer * -radeon_pb_buffer(struct r300_winsys_buffer *buffer) +pb_buffer(struct r300_winsys_bo *buffer) { return (struct pb_buffer *)buffer; } -struct pb_manager *radeon_drm_bufmgr_create(struct radeon_drm_winsys *rws); -struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr, - uint32_t handle); -void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr); -boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf, - struct winsys_handle *whandle); -void radeon_drm_bufmgr_init_functions(struct radeon_drm_winsys *ws); - #endif diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c deleted file mode 100644 index dc4b51747f..0000000000 --- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c +++ /dev/null @@ -1,564 +0,0 @@ -#include "radeon_cs_gem.h" -#include "radeon_drm_buffer.h" - -#include "util/u_hash_table.h" -#include "util/u_memory.h" -#include "util/u_simple_list.h" -#include "pipebuffer/pb_bufmgr.h" -#include "os/os_thread.h" - -#include "state_tracker/drm_driver.h" - -#include <radeon_drm.h> -#include <radeon_bo_gem.h> -#include <sys/ioctl.h> - -struct radeon_drm_bufmgr; - -struct radeon_drm_buffer { - struct pb_buffer base; - struct radeon_drm_bufmgr *mgr; - - struct radeon_bo *bo; - - boolean flinked; - uint32_t flink; - - struct radeon_drm_buffer *next, *prev; -}; - -extern const struct pb_vtbl radeon_drm_buffer_vtbl; - - -static INLINE struct radeon_drm_buffer * -radeon_drm_buffer(struct pb_buffer *buf) -{ - assert(buf); - assert(buf->vtbl == &radeon_drm_buffer_vtbl); - return (struct radeon_drm_buffer *)buf; -} - -struct radeon_drm_bufmgr { - /* Base class. */ - struct pb_manager base; - - /* Winsys. */ - struct radeon_drm_winsys *rws; - - /* List of mapped buffers and its mutex. */ - struct radeon_drm_buffer buffer_map_list; - pipe_mutex buffer_map_list_mutex; - - /* List of buffer handles and its mutex. */ - struct util_hash_table *buffer_handles; - pipe_mutex buffer_handles_mutex; -}; - -static INLINE struct radeon_drm_bufmgr * -radeon_drm_bufmgr(struct pb_manager *mgr) -{ - assert(mgr); - return (struct radeon_drm_bufmgr *)mgr; -} - -static void -radeon_drm_buffer_destroy(struct pb_buffer *_buf) -{ - struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); - int name; - - if (buf->bo->ptr != NULL) { - pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); - /* Now test it again inside the mutex. */ - if (buf->bo->ptr != NULL) { - remove_from_list(buf); - radeon_bo_unmap(buf->bo); - buf->bo->ptr = NULL; - } - pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); - } - name = radeon_gem_name_bo(buf->bo); - if (name) { - pipe_mutex_lock(buf->mgr->buffer_handles_mutex); - util_hash_table_remove(buf->mgr->buffer_handles, - (void*)(uintptr_t)name); - pipe_mutex_unlock(buf->mgr->buffer_handles_mutex); - } - radeon_bo_unref(buf->bo); - - FREE(buf); -} - -static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage) -{ - unsigned res = 0; - - if (usage & PIPE_TRANSFER_READ) - res |= PB_USAGE_CPU_READ; - - if (usage & PIPE_TRANSFER_WRITE) - res |= PB_USAGE_CPU_WRITE; - - if (usage & PIPE_TRANSFER_DONTBLOCK) - res |= PB_USAGE_DONTBLOCK; - - if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) - res |= PB_USAGE_UNSYNCHRONIZED; - - return res; -} - -static void * -radeon_drm_buffer_map_internal(struct pb_buffer *_buf, - unsigned flags, void *flush_ctx) -{ - struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); - struct radeon_drm_cs *cs = flush_ctx; - int write = 0; - - /* Note how we use radeon_bo_is_referenced_by_cs here. There are - * basically two places this map function can be called from: - * - pb_map - * - create_buffer (in the buffer reuse case) - * - * Since pb managers are per-winsys managers, not per-context managers, - * and we shouldn't reuse buffers if they are in-use in any context, - * we simply ask: is this buffer referenced by *any* CS? - * - * The problem with buffer_create is that it comes from pipe_screen, - * so we have no CS to look at, though luckily the following code - * is sufficient to tell whether the buffer is in use. */ - if (flags & PB_USAGE_DONTBLOCK) { - if (_buf->base.usage & RADEON_PB_USAGE_VERTEX) - if (radeon_bo_is_referenced_by_cs(buf->bo, NULL)) - return NULL; - } - - if (buf->bo->ptr != NULL) { - pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); - /* Now test ptr again inside the mutex. We might have gotten a race - * during the first test. */ - if (buf->bo->ptr != NULL) { - remove_from_list(buf); - } - pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); - return buf->bo->ptr; - } - - if (flags & PB_USAGE_DONTBLOCK) { - uint32_t domain; - if (radeon_bo_is_busy(buf->bo, &domain)) - return NULL; - } - - /* If we don't have any CS and the buffer is referenced, - * we cannot flush. */ - assert(cs || !radeon_bo_is_referenced_by_cs(buf->bo, NULL)); - - if (cs && radeon_bo_is_referenced_by_cs(buf->bo, cs->cs)) { - cs->flush_cs(cs->flush_data); - } - - if (flags & PB_USAGE_CPU_WRITE) { - write = 1; - } - - if (radeon_bo_map(buf->bo, write)) { - return NULL; - } - - pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); - remove_from_list(buf); - pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); - return buf->bo->ptr; -} - -static void -radeon_drm_buffer_unmap_internal(struct pb_buffer *_buf) -{ - struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); - pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); - if (is_empty_list(buf)) { /* = is not inserted... */ - insert_at_tail(&buf->mgr->buffer_map_list, buf); - } - pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); -} - -static void -radeon_drm_buffer_get_base_buffer(struct pb_buffer *buf, - struct pb_buffer **base_buf, - unsigned *offset) -{ - *base_buf = buf; - *offset = 0; -} - - -static enum pipe_error -radeon_drm_buffer_validate(struct pb_buffer *_buf, - struct pb_validate *vl, - unsigned flags) -{ - /* Always pinned */ - return PIPE_OK; -} - -static void -radeon_drm_buffer_fence(struct pb_buffer *buf, - struct pipe_fence_handle *fence) -{ -} - -const struct pb_vtbl radeon_drm_buffer_vtbl = { - radeon_drm_buffer_destroy, - radeon_drm_buffer_map_internal, - radeon_drm_buffer_unmap_internal, - radeon_drm_buffer_validate, - radeon_drm_buffer_fence, - radeon_drm_buffer_get_base_buffer, -}; - -static struct pb_buffer * -radeon_drm_bufmgr_create_buffer_from_handle_unsafe(struct pb_manager *_mgr, - uint32_t handle) -{ - struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); - struct radeon_drm_winsys *rws = mgr->rws; - struct radeon_drm_buffer *buf; - struct radeon_bo *bo; - - buf = util_hash_table_get(mgr->buffer_handles, (void*)(uintptr_t)handle); - - if (buf) { - struct pb_buffer *b = NULL; - pb_reference(&b, &buf->base); - return b; - } - - bo = radeon_bo_open(rws->bom, handle, 0, - 0, 0, 0); - if (bo == NULL) - return NULL; - - buf = CALLOC_STRUCT(radeon_drm_buffer); - if (!buf) { - radeon_bo_unref(bo); - return NULL; - } - - make_empty_list(buf); - - pipe_reference_init(&buf->base.base.reference, 1); - buf->base.base.alignment = 0; - buf->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ; - buf->base.base.size = bo->size; - buf->base.vtbl = &radeon_drm_buffer_vtbl; - buf->mgr = mgr; - - buf->bo = bo; - - util_hash_table_set(mgr->buffer_handles, (void*)(uintptr_t)handle, buf); - - return &buf->base; -} - -struct pb_buffer * -radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr, - uint32_t handle) -{ - struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); - struct pb_buffer *pb; - - pipe_mutex_lock(mgr->buffer_handles_mutex); - pb = radeon_drm_bufmgr_create_buffer_from_handle_unsafe(_mgr, handle); - pipe_mutex_unlock(mgr->buffer_handles_mutex); - - return pb; -} - -static struct pb_buffer * -radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr, - pb_size size, - const struct pb_desc *desc) -{ - struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); - struct radeon_drm_winsys *rws = mgr->rws; - struct radeon_drm_buffer *buf; - uint32_t domain; - - buf = CALLOC_STRUCT(radeon_drm_buffer); - if (!buf) - goto error1; - - pipe_reference_init(&buf->base.base.reference, 1); - buf->base.base.alignment = desc->alignment; - buf->base.base.usage = desc->usage; - buf->base.base.size = size; - buf->base.vtbl = &radeon_drm_buffer_vtbl; - buf->mgr = mgr; - - make_empty_list(buf); - - domain = - (desc->usage & RADEON_PB_USAGE_DOMAIN_GTT ? RADEON_GEM_DOMAIN_GTT : 0) | - (desc->usage & RADEON_PB_USAGE_DOMAIN_VRAM ? RADEON_GEM_DOMAIN_VRAM : 0); - - buf->bo = radeon_bo_open(rws->bom, 0, size, - desc->alignment, domain, 0); - if (buf->bo == NULL) - goto error2; - - return &buf->base; - - error2: - FREE(buf); - error1: - return NULL; -} - -static void -radeon_drm_bufmgr_flush(struct pb_manager *mgr) -{ - /* NOP */ -} - -static void -radeon_drm_bufmgr_destroy(struct pb_manager *_mgr) -{ - struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); - util_hash_table_destroy(mgr->buffer_handles); - pipe_mutex_destroy(mgr->buffer_map_list_mutex); - pipe_mutex_destroy(mgr->buffer_handles_mutex); - FREE(mgr); -} - -static unsigned handle_hash(void *key) -{ - return (unsigned)key; -} - -static int handle_compare(void *key1, void *key2) -{ - return !((int)key1 == (int)key2); -} - -struct pb_manager * -radeon_drm_bufmgr_create(struct radeon_drm_winsys *rws) -{ - struct radeon_drm_bufmgr *mgr; - - mgr = CALLOC_STRUCT(radeon_drm_bufmgr); - if (!mgr) - return NULL; - - mgr->base.destroy = radeon_drm_bufmgr_destroy; - mgr->base.create_buffer = radeon_drm_bufmgr_create_buffer; - mgr->base.flush = radeon_drm_bufmgr_flush; - - mgr->rws = rws; - make_empty_list(&mgr->buffer_map_list); - mgr->buffer_handles = util_hash_table_create(handle_hash, handle_compare); - pipe_mutex_init(mgr->buffer_map_list_mutex); - pipe_mutex_init(mgr->buffer_handles_mutex); - return &mgr->base; -} - -static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf) -{ - struct radeon_drm_buffer *buf = NULL; - - if (_buf->vtbl == &radeon_drm_buffer_vtbl) { - buf = radeon_drm_buffer(_buf); - } else { - struct pb_buffer *base_buf; - pb_size offset; - pb_get_base_buffer(_buf, &base_buf, &offset); - - if (base_buf->vtbl == &radeon_drm_buffer_vtbl) - buf = radeon_drm_buffer(base_buf); - } - - return buf; -} - -static void *radeon_drm_buffer_map(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf, - struct r300_winsys_cs *cs, - enum pipe_transfer_usage usage) -{ - struct pb_buffer *_buf = radeon_pb_buffer(buf); - - return pb_map(_buf, get_pb_usage_from_transfer_flags(usage), radeon_drm_cs(cs)); -} - -static void radeon_drm_buffer_unmap(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf) -{ - struct pb_buffer *_buf = radeon_pb_buffer(buf); - - pb_unmap(_buf); -} - -boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf, - struct winsys_handle *whandle) -{ - struct drm_gem_flink flink; - struct radeon_drm_buffer *buf = get_drm_buffer(_buf); - - if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { - if (!buf->flinked) { - flink.handle = buf->bo->handle; - - if (ioctl(buf->mgr->rws->fd, DRM_IOCTL_GEM_FLINK, &flink)) { - return FALSE; - } - - buf->flinked = TRUE; - buf->flink = flink.name; - } - whandle->handle = buf->flink; - } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { - whandle->handle = buf->bo->handle; - } - return TRUE; -} - -static void radeon_drm_buffer_get_tiling(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *_buf, - enum r300_buffer_tiling *microtiled, - enum r300_buffer_tiling *macrotiled) -{ - struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf)); - uint32_t flags = 0, pitch; - - radeon_bo_get_tiling(buf->bo, &flags, &pitch); - - *microtiled = R300_BUFFER_LINEAR; - *macrotiled = R300_BUFFER_LINEAR; - if (flags & RADEON_BO_FLAGS_MICRO_TILE) - *microtiled = R300_BUFFER_TILED; - - if (flags & RADEON_BO_FLAGS_MACRO_TILE) - *macrotiled = R300_BUFFER_TILED; -} - -static void radeon_drm_buffer_set_tiling(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *_buf, - enum r300_buffer_tiling microtiled, - enum r300_buffer_tiling macrotiled, - uint32_t pitch) -{ - struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf)); - uint32_t flags = 0; - if (microtiled == R300_BUFFER_TILED) - flags |= RADEON_BO_FLAGS_MICRO_TILE; -/* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */ -#ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE - else if (microtiled == R300_BUFFER_SQUARETILED) - flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE; -#endif - if (macrotiled == R300_BUFFER_TILED) - flags |= RADEON_BO_FLAGS_MACRO_TILE; - - radeon_bo_set_tiling(buf->bo, flags, pitch); -} - -static void radeon_drm_bufmgr_add_buffer(struct r300_winsys_cs *rcs, - struct r300_winsys_cs_buffer *_buf, - enum r300_buffer_domain rd, - enum r300_buffer_domain wd) -{ - struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - struct radeon_bo *bo = (struct radeon_bo*)_buf; - - radeon_cs_space_add_persistent_bo(cs->cs, bo, rd, wd); -} - -static void radeon_drm_bufmgr_write_reloc(struct r300_winsys_cs *rcs, - struct r300_winsys_cs_buffer *_buf, - enum r300_buffer_domain rd, - enum r300_buffer_domain wd) -{ - struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - struct radeon_bo *bo = (struct radeon_bo*)_buf; - int retval; - - cs->cs->cdw = cs->base.cdw; - retval = radeon_cs_write_reloc(cs->cs, bo, rd, wd, 0); - cs->base.cdw = cs->cs->cdw; - if (retval) { - fprintf(stderr, "radeon: Relocation of %p (%d, %d, %d) failed!\n", - bo, rd, wd, 0); - } -} - -static struct r300_winsys_cs_buffer *radeon_drm_get_cs_handle( - struct r300_winsys_screen *rws, - struct r300_winsys_buffer *_buf) -{ - /* return pure radeon_bo. */ - return (struct r300_winsys_cs_buffer*) - get_drm_buffer(radeon_pb_buffer(_buf))->bo; -} - -static boolean radeon_drm_is_buffer_referenced(struct r300_winsys_cs *rcs, - struct r300_winsys_cs_buffer *_buf, - enum r300_reference_domain domain) -{ - struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - struct radeon_bo *bo = (struct radeon_bo*)_buf; - uint32_t tmp; - - if (domain & R300_REF_CS) { - if (radeon_bo_is_referenced_by_cs(bo, cs->cs)) { - return TRUE; - } - } - - if (domain & R300_REF_HW) { - if (radeon_bo_is_busy(bo, &tmp)) { - return TRUE; - } - } - - return FALSE; -} - -void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr) -{ - struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); - struct radeon_drm_buffer *rpb, *t_rpb; - - pipe_mutex_lock(mgr->buffer_map_list_mutex); - - foreach_s(rpb, t_rpb, &mgr->buffer_map_list) { - radeon_bo_unmap(rpb->bo); - rpb->bo->ptr = NULL; - remove_from_list(rpb); - } - - make_empty_list(&mgr->buffer_map_list); - - pipe_mutex_unlock(mgr->buffer_map_list_mutex); -} - -static void radeon_drm_buffer_wait(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *_buf) -{ - struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf)); - - radeon_bo_wait(buf->bo); -} - -void radeon_drm_bufmgr_init_functions(struct radeon_drm_winsys *ws) -{ - ws->base.buffer_get_cs_handle = radeon_drm_get_cs_handle; - ws->base.buffer_set_tiling = radeon_drm_buffer_set_tiling; - ws->base.buffer_get_tiling = radeon_drm_buffer_get_tiling; - ws->base.buffer_map = radeon_drm_buffer_map; - ws->base.buffer_unmap = radeon_drm_buffer_unmap; - ws->base.buffer_wait = radeon_drm_buffer_wait; - ws->base.cs_is_buffer_referenced = radeon_drm_is_buffer_referenced; - ws->base.cs_add_buffer = radeon_drm_bufmgr_add_buffer; - ws->base.cs_write_reloc = radeon_drm_bufmgr_write_reloc; -} diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_common.c b/src/gallium/winsys/radeon/drm/radeon_drm_common.c index 6bc6244115..72c2ff1112 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_common.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_common.c @@ -1,5 +1,6 @@ /* * Copyright © 2009 Corbin Simpson + * Copyright © 2011 Marek Olšák <maraeo@gmail.com> * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining @@ -27,39 +28,35 @@ * Authors: * Corbin Simpson <MostAwesomeDude@gmail.com> * Joakim Sindholt <opensource@zhasha.com> + * Marek Olšák <maraeo@gmail.com> */ #include "radeon_winsys.h" -#include "radeon_drm_buffer.h" +#include "radeon_drm_bo.h" +#include "radeon_drm_cs.h" #include "radeon_drm_public.h" #include "pipebuffer/pb_bufmgr.h" #include "util/u_memory.h" -#include "state_tracker/drm_driver.h" - -#include <radeon_drm.h> -#include <radeon_bo_gem.h> -#include <radeon_cs_gem.h> #include <xf86drm.h> #include <stdio.h> - -/* Enable/disable Hyper-Z access. Return TRUE on success. */ -static boolean radeon_set_hyperz_access(int fd, boolean enable) -{ #ifndef RADEON_INFO_WANT_HYPERZ #define RADEON_INFO_WANT_HYPERZ 7 #endif +#ifndef RADEON_INFO_WANT_CMASK +#define RADEON_INFO_WANT_CMASK 8 +#endif +/* Enable/disable feature access. Return TRUE on success. */ +static boolean radeon_set_fd_access(int fd, unsigned request, boolean enable) +{ struct drm_radeon_info info = {0}; unsigned value = enable ? 1 : 0; - if (!debug_get_bool_option("RADEON_HYPERZ", FALSE)) - return FALSE; - info.value = (unsigned long)&value; - info.request = RADEON_INFO_WANT_HYPERZ; + info.request = request; if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0) return FALSE; @@ -99,28 +96,21 @@ static void do_ioctls(struct radeon_drm_winsys *winsys) * we don't actually use the info for anything yet. */ version = drmGetVersion(winsys->fd); - if (version->version_major != 2) { + if (version->version_major != 2 || + version->version_minor < 3) { fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is " - "only compatible with 2.x.x\n", __FUNCTION__, - version->version_major, version->version_minor, + "only compatible with 2.3.x (kernel 2.6.34) and later.\n", + __FUNCTION__, + version->version_major, + version->version_minor, version->version_patchlevel); drmFreeVersion(version); exit(1); } -/* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */ -#ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE - // Supported since 2.1.0. - winsys->squaretiling = version->version_major > 2 || - version->version_minor >= 1; -#endif - - winsys->drm_2_3_0 = version->version_major > 2 || - version->version_minor >= 3; - - winsys->drm_2_6_0 = version->version_major > 2 || - (version->version_major == 2 && - version->version_minor >= 6); + winsys->drm_major = version->version_major; + winsys->drm_minor = version->version_minor; + winsys->drm_patchlevel = version->version_patchlevel; info.request = RADEON_INFO_DEVICE_ID; retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_INFO, &info, sizeof(info)); @@ -149,7 +139,15 @@ static void do_ioctls(struct radeon_drm_winsys *winsys) } winsys->z_pipes = target; - winsys->hyperz = radeon_set_hyperz_access(winsys->fd, TRUE); + if (debug_get_bool_option("RADEON_HYPERZ", FALSE)) { + winsys->hyperz = radeon_set_fd_access(winsys->fd, + RADEON_INFO_WANT_HYPERZ, TRUE); + } + + if (debug_get_bool_option("RADEON_CMASK", FALSE)) { + winsys->aacompress = radeon_set_fd_access(winsys->fd, + RADEON_INFO_WANT_CMASK, TRUE); + } retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_GEM_INFO, &gem_info, sizeof(gem_info)); @@ -161,18 +159,9 @@ static void do_ioctls(struct radeon_drm_winsys *winsys) winsys->gart_size = gem_info.gart_size; winsys->vram_size = gem_info.vram_size; - debug_printf("radeon: Successfully grabbed chipset info from kernel!\n" - "radeon: DRM version: %d.%d.%d ID: 0x%04x GB: %d Z: %d\n" - "radeon: GART size: %d MB VRAM size: %d MB\n" - "radeon: HyperZ: %s\n", - version->version_major, version->version_minor, - version->version_patchlevel, winsys->pci_id, - winsys->gb_pipes, winsys->z_pipes, - winsys->gart_size / 1024 / 1024, - winsys->vram_size / 1024 / 1024, - winsys->hyperz ? "YES" : "NO"); - drmFreeVersion(version); + + winsys->num_cpus = sysconf(_SC_NPROCESSORS_ONLN); } static void radeon_winsys_destroy(struct r300_winsys_screen *rws) @@ -181,12 +170,43 @@ static void radeon_winsys_destroy(struct r300_winsys_screen *rws) ws->cman->destroy(ws->cman); ws->kman->destroy(ws->kman); - - radeon_bo_manager_gem_dtor(ws->bom); - radeon_cs_manager_gem_dtor(ws->csm); FREE(rws); } +static uint32_t radeon_get_value(struct r300_winsys_screen *rws, + enum r300_value_id id) +{ + struct radeon_drm_winsys *ws = (struct radeon_drm_winsys *)rws; + + switch(id) { + case R300_VID_PCI_ID: + return ws->pci_id; + case R300_VID_GB_PIPES: + return ws->gb_pipes; + case R300_VID_Z_PIPES: + return ws->z_pipes; + case R300_VID_GART_SIZE: + return ws->gart_size; + case R300_VID_VRAM_SIZE: + return ws->vram_size; + case R300_VID_DRM_MAJOR: + return ws->drm_major; + case R300_VID_DRM_MINOR: + return ws->drm_minor; + case R300_VID_DRM_PATCHLEVEL: + return ws->drm_patchlevel; + case R300_VID_DRM_2_6_0: + return ws->drm_major*100 + ws->drm_minor >= 206; + case R300_VID_DRM_2_8_0: + return ws->drm_major*100 + ws->drm_minor >= 208; + case R300_CAN_HYPERZ: + return ws->hyperz; + case R300_CAN_AACOMPRESS: + return ws->aacompress; + } + return 0; +} + struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd) { struct radeon_drm_winsys *ws = CALLOC_STRUCT(radeon_drm_winsys); @@ -202,13 +222,7 @@ struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd) } /* Create managers. */ - ws->bom = radeon_bo_manager_gem_ctor(fd); - if (!ws->bom) - goto fail; - ws->csm = radeon_cs_manager_gem_ctor(fd); - if (!ws->csm) - goto fail; - ws->kman = radeon_drm_bufmgr_create(ws); + ws->kman = radeon_bomgr_create(ws); if (!ws->kman) goto fail; ws->cman = pb_cache_manager_create(ws->kman, 1000000); @@ -217,23 +231,18 @@ struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd) /* Set functions. */ ws->base.destroy = radeon_winsys_destroy; + ws->base.get_value = radeon_get_value; - radeon_drm_bufmgr_init_functions(ws); - radeon_winsys_init_functions(ws); + radeon_bomgr_init_functions(ws); + radeon_drm_cs_init_functions(ws); return &ws->base; fail: - if (ws->bom) - radeon_bo_manager_gem_dtor(ws->bom); - if (ws->csm) - radeon_cs_manager_gem_dtor(ws->csm); - if (ws->cman) ws->cman->destroy(ws->cman); if (ws->kman) ws->kman->destroy(ws->kman); - FREE(ws); return NULL; } diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c new file mode 100644 index 0000000000..951791a172 --- /dev/null +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c @@ -0,0 +1,446 @@ +/* + * Copyright © 2008 Jérôme Glisse + * Copyright © 2010 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ +/* + * Authors: + * Marek Olšák <maraeo@gmail.com> + * + * Based on work from libdrm_radeon by: + * Aapo Tahkola <aet@rasterburn.org> + * Nicolai Haehnle <prefect_@gmx.net> + * Jérôme Glisse <glisse@freedesktop.org> + */ + +/* + This file replaces libdrm's radeon_cs_gem with our own implemention. + It's optimized specifically for r300g, but r600g could use it as well. + Reloc writes and space checking are faster and simpler than their + counterparts in libdrm (the time complexity of all the functions + is O(1) in nearly all scenarios, thanks to hashing). + + It works like this: + + cs_add_reloc(cs, buf, read_domain, write_domain) adds a new relocation and + also adds the size of 'buf' to the used_gart and used_vram winsys variables + based on the domains, which are simply or'd for the accounting purposes. + The adding is skipped if the reloc is already present in the list, but it + accounts any newly-referenced domains. + + cs_validate is then called, which just checks: + used_vram/gart < vram/gart_size * 0.8 + The 0.8 number allows for some memory fragmentation. If the validation + fails, the pipe driver flushes CS and tries do the validation again, + i.e. it validates only that one operation. If it fails again, it drops + the operation on the floor and prints some nasty message to stderr. + (done in the pipe driver) + + cs_write_reloc(cs, buf) just writes a reloc that has been added using + cs_add_reloc. The read_domain and write_domain parameters have been removed, + because we already specify them in cs_add_reloc. +*/ + +#include "radeon_drm_cs.h" + +#include "util/u_memory.h" + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <xf86drm.h> + +#define RELOC_DWORDS (sizeof(struct drm_radeon_cs_reloc) / sizeof(uint32_t)) + +static boolean radeon_init_cs_context(struct radeon_cs_context *csc, int fd) +{ + csc->fd = fd; + csc->nrelocs = 512; + csc->relocs_bo = (struct radeon_bo**) + CALLOC(1, csc->nrelocs * sizeof(struct radeon_bo*)); + if (!csc->relocs_bo) { + return FALSE; + } + + csc->relocs = (struct drm_radeon_cs_reloc*) + CALLOC(1, csc->nrelocs * sizeof(struct drm_radeon_cs_reloc)); + if (!csc->relocs) { + FREE(csc->relocs_bo); + return FALSE; + } + + csc->chunks[0].chunk_id = RADEON_CHUNK_ID_IB; + csc->chunks[0].length_dw = 0; + csc->chunks[0].chunk_data = (uint64_t)(uintptr_t)csc->buf; + csc->chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS; + csc->chunks[1].length_dw = 0; + csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs; + + csc->chunk_array[0] = (uint64_t)(uintptr_t)&csc->chunks[0]; + csc->chunk_array[1] = (uint64_t)(uintptr_t)&csc->chunks[1]; + + csc->cs.num_chunks = 2; + csc->cs.chunks = (uint64_t)(uintptr_t)csc->chunk_array; + return TRUE; +} + +static void radeon_cs_context_cleanup(struct radeon_cs_context *csc) +{ + unsigned i; + + for (i = 0; i < csc->crelocs; i++) { + p_atomic_dec(&csc->relocs_bo[i]->num_cs_references); + radeon_bo_unref(csc->relocs_bo[i]); + csc->relocs_bo[i] = NULL; + } + + csc->crelocs = 0; + csc->chunks[0].length_dw = 0; + csc->chunks[1].length_dw = 0; + csc->used_gart = 0; + csc->used_vram = 0; + memset(csc->is_handle_added, 0, sizeof(csc->is_handle_added)); +} + +static void radeon_destroy_cs_context(struct radeon_cs_context *csc) +{ + radeon_cs_context_cleanup(csc); + FREE(csc->relocs_bo); + FREE(csc->relocs); +} + +static struct r300_winsys_cs *radeon_drm_cs_create(struct r300_winsys_screen *rws) +{ + struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); + struct radeon_drm_cs *cs; + + cs = CALLOC_STRUCT(radeon_drm_cs); + if (!cs) { + return NULL; + } + + cs->ws = ws; + + if (!radeon_init_cs_context(&cs->csc1, cs->ws->fd)) { + FREE(cs); + return NULL; + } + if (!radeon_init_cs_context(&cs->csc2, cs->ws->fd)) { + radeon_destroy_cs_context(&cs->csc1); + FREE(cs); + return NULL; + } + + /* Set the first command buffer as current. */ + cs->csc = &cs->csc1; + cs->cst = &cs->csc2; + cs->base.buf = cs->csc->buf; + + p_atomic_inc(&ws->num_cs); + return &cs->base; +} + +#define OUT_CS(cs, value) (cs)->buf[(cs)->cdw++] = (value) + +static INLINE void update_domains(struct drm_radeon_cs_reloc *reloc, + enum r300_buffer_domain rd, + enum r300_buffer_domain wd, + enum r300_buffer_domain *added_domains) +{ + *added_domains = (rd | wd) & ~(reloc->read_domains | reloc->write_domain); + + if (reloc->read_domains & wd) { + reloc->read_domains = rd; + reloc->write_domain = wd; + } else if (rd & reloc->write_domain) { + reloc->read_domains = rd; + reloc->write_domain |= wd; + } else { + reloc->read_domains |= rd; + reloc->write_domain |= wd; + } +} + +int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo) +{ + struct drm_radeon_cs_reloc *reloc; + unsigned i; + unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1); + + if (csc->is_handle_added[hash]) { + reloc = csc->relocs_hashlist[hash]; + if (reloc->handle == bo->handle) { + return csc->reloc_indices_hashlist[hash]; + } + + /* Hash collision, look for the BO in the list of relocs linearly. */ + for (i = csc->crelocs; i != 0;) { + --i; + reloc = &csc->relocs[i]; + if (reloc->handle == bo->handle) { + /* Put this reloc in the hash list. + * This will prevent additional hash collisions if there are + * several subsequent get_reloc calls of the same buffer. + * + * Example: Assuming buffers A,B,C collide in the hash list, + * the following sequence of relocs: + * AAAAAAAAAAABBBBBBBBBBBBBBCCCCCCCC + * will collide here: ^ and here: ^, + * meaning that we should get very few collisions in the end. */ + csc->relocs_hashlist[hash] = reloc; + csc->reloc_indices_hashlist[hash] = i; + /*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/ + return i; + } + } + } + + return -1; +} + +static void radeon_add_reloc(struct radeon_cs_context *csc, + struct radeon_bo *bo, + enum r300_buffer_domain rd, + enum r300_buffer_domain wd, + enum r300_buffer_domain *added_domains) +{ + struct drm_radeon_cs_reloc *reloc; + unsigned i; + unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1); + + if (csc->is_handle_added[hash]) { + reloc = csc->relocs_hashlist[hash]; + if (reloc->handle == bo->handle) { + update_domains(reloc, rd, wd, added_domains); + return; + } + + /* Hash collision, look for the BO in the list of relocs linearly. */ + for (i = csc->crelocs; i != 0;) { + --i; + reloc = &csc->relocs[i]; + if (reloc->handle == bo->handle) { + update_domains(reloc, rd, wd, added_domains); + + csc->relocs_hashlist[hash] = reloc; + csc->reloc_indices_hashlist[hash] = i; + /*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/ + return; + } + } + } + + /* New relocation, check if the backing array is large enough. */ + if (csc->crelocs >= csc->nrelocs) { + uint32_t size; + csc->nrelocs += 10; + + size = csc->nrelocs * sizeof(struct radeon_bo*); + csc->relocs_bo = (struct radeon_bo**)realloc(csc->relocs_bo, size); + + size = csc->nrelocs * sizeof(struct drm_radeon_cs_reloc); + csc->relocs = (struct drm_radeon_cs_reloc*)realloc(csc->relocs, size); + + csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs; + } + + /* Initialize the new relocation. */ + radeon_bo_ref(bo); + p_atomic_inc(&bo->num_cs_references); + csc->relocs_bo[csc->crelocs] = bo; + reloc = &csc->relocs[csc->crelocs]; + reloc->handle = bo->handle; + reloc->read_domains = rd; + reloc->write_domain = wd; + reloc->flags = 0; + + csc->is_handle_added[hash] = TRUE; + csc->relocs_hashlist[hash] = reloc; + csc->reloc_indices_hashlist[hash] = csc->crelocs; + + csc->chunks[1].length_dw += RELOC_DWORDS; + csc->crelocs++; + + *added_domains = rd | wd; +} + +static void radeon_drm_cs_add_reloc(struct r300_winsys_cs *rcs, + struct r300_winsys_cs_handle *buf, + enum r300_buffer_domain rd, + enum r300_buffer_domain wd) +{ + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + struct radeon_bo *bo = (struct radeon_bo*)buf; + enum r300_buffer_domain added_domains; + + radeon_add_reloc(cs->csc, bo, rd, wd, &added_domains); + + if (!added_domains) + return; + + if (added_domains & R300_DOMAIN_GTT) + cs->csc->used_gart += bo->size; + if (added_domains & R300_DOMAIN_VRAM) + cs->csc->used_vram += bo->size; +} + +static boolean radeon_drm_cs_validate(struct r300_winsys_cs *rcs) +{ + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + + return cs->csc->used_gart < cs->ws->gart_size * 0.8 && + cs->csc->used_vram < cs->ws->vram_size * 0.8; +} + +static void radeon_drm_cs_write_reloc(struct r300_winsys_cs *rcs, + struct r300_winsys_cs_handle *buf) +{ + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + struct radeon_bo *bo = (struct radeon_bo*)buf; + + unsigned index = radeon_get_reloc(cs->csc, bo); + + if (index == -1) { + fprintf(stderr, "r300: Cannot get a relocation in %s.\n", __func__); + return; + } + + OUT_CS(&cs->base, 0xc0001000); + OUT_CS(&cs->base, index * RELOC_DWORDS); +} + +static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param) +{ + struct radeon_cs_context *csc = (struct radeon_cs_context*)param; + unsigned i; + + if (drmCommandWriteRead(csc->fd, DRM_RADEON_CS, + &csc->cs, sizeof(struct drm_radeon_cs))) { + if (debug_get_bool_option("RADEON_DUMP_CS", FALSE)) { + unsigned i; + + fprintf(stderr, "radeon: The kernel rejected CS, dumping...\n"); + for (i = 0; i < csc->chunks[0].length_dw; i++) { + fprintf(stderr, "0x%08X\n", csc->buf[i]); + } + } else { + fprintf(stderr, "radeon: The kernel rejected CS, " + "see dmesg for more information.\n"); + } + } + + for (i = 0; i < csc->crelocs; i++) + p_atomic_dec(&csc->relocs_bo[i]->num_active_ioctls); + return NULL; +} + +void radeon_drm_cs_sync_flush(struct radeon_drm_cs *cs) +{ + /* Wait for any pending ioctl to complete. */ + if (cs->thread) { + pipe_thread_wait(cs->thread); + cs->thread = 0; + } +} + +DEBUG_GET_ONCE_BOOL_OPTION(thread, "RADEON_THREAD", TRUE) + +static void radeon_drm_cs_flush(struct r300_winsys_cs *rcs, unsigned flags) +{ + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + struct radeon_cs_context *tmp; + + radeon_drm_cs_sync_flush(cs); + + /* If the CS is not empty, emit it in a newly-spawned thread. */ + if (cs->base.cdw) { + unsigned i, crelocs = cs->csc->crelocs; + + cs->csc->chunks[0].length_dw = cs->base.cdw; + + for (i = 0; i < crelocs; i++) + p_atomic_inc(&cs->csc->relocs_bo[i]->num_active_ioctls); + + if (cs->ws->num_cpus > 1 && debug_get_option_thread() && + (flags & R300_FLUSH_ASYNC)) { + cs->thread = pipe_thread_create(radeon_drm_cs_emit_ioctl, cs->csc); + assert(cs->thread); + } else { + radeon_drm_cs_emit_ioctl(cs->csc); + } + } + + /* Flip command streams. */ + tmp = cs->csc; + cs->csc = cs->cst; + cs->cst = tmp; + + /* Prepare a new CS. */ + radeon_cs_context_cleanup(cs->csc); + + cs->base.buf = cs->csc->buf; + cs->base.cdw = 0; +} + +static void radeon_drm_cs_destroy(struct r300_winsys_cs *rcs) +{ + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + radeon_drm_cs_sync_flush(cs); + radeon_cs_context_cleanup(&cs->csc1); + radeon_cs_context_cleanup(&cs->csc2); + p_atomic_dec(&cs->ws->num_cs); + radeon_destroy_cs_context(&cs->csc1); + radeon_destroy_cs_context(&cs->csc2); + FREE(cs); +} + +static void radeon_drm_cs_set_flush(struct r300_winsys_cs *rcs, + void (*flush)(void *ctx, unsigned flags), + void *user) +{ + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + cs->flush_cs = flush; + cs->flush_data = user; +} + +static boolean radeon_bo_is_referenced(struct r300_winsys_cs *rcs, + struct r300_winsys_cs_handle *_buf) +{ + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + struct radeon_bo *bo = (struct radeon_bo*)_buf; + + return radeon_bo_is_referenced_by_cs(cs, bo); +} + +void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws) +{ + ws->base.cs_create = radeon_drm_cs_create; + ws->base.cs_destroy = radeon_drm_cs_destroy; + ws->base.cs_add_reloc = radeon_drm_cs_add_reloc; + ws->base.cs_validate = radeon_drm_cs_validate; + ws->base.cs_write_reloc = radeon_drm_cs_write_reloc; + ws->base.cs_flush = radeon_drm_cs_flush; + ws->base.cs_set_flush = radeon_drm_cs_set_flush; + ws->base.cs_is_buffer_referenced = radeon_bo_is_referenced; +} diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h new file mode 100644 index 0000000000..dfaa161c31 --- /dev/null +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h @@ -0,0 +1,102 @@ +/* + * Copyright © 2011 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + +#ifndef RADEON_DRM_CS_H +#define RADEON_DRM_CS_H + +#include "radeon_drm_bo.h" +#include <radeon_drm.h> + +struct radeon_cs_context { + uint32_t buf[R300_MAX_CMDBUF_DWORDS]; + + int fd; + struct drm_radeon_cs cs; + struct drm_radeon_cs_chunk chunks[2]; + uint64_t chunk_array[2]; + + /* Relocs. */ + unsigned nrelocs; + unsigned crelocs; + struct radeon_bo **relocs_bo; + struct drm_radeon_cs_reloc *relocs; + + /* 0 = BO not added, 1 = BO added */ + char is_handle_added[256]; + struct drm_radeon_cs_reloc *relocs_hashlist[256]; + unsigned reloc_indices_hashlist[256]; + + unsigned used_vram; + unsigned used_gart; +}; + +struct radeon_drm_cs { + struct r300_winsys_cs base; + + /* We flip between these two CS. While one is being consumed + * by the kernel in another thread, the other one is being filled + * by the pipe driver. */ + struct radeon_cs_context csc1; + struct radeon_cs_context csc2; + /* The currently-used CS. */ + struct radeon_cs_context *csc; + /* The CS being currently-owned by the other thread. */ + struct radeon_cs_context *cst; + + /* The winsys. */ + struct radeon_drm_winsys *ws; + + /* Flush CS. */ + void (*flush_cs)(void *ctx, unsigned flags); + void *flush_data; + + pipe_thread thread; +}; + +int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo); + +static INLINE struct radeon_drm_cs * +radeon_drm_cs(struct r300_winsys_cs *base) +{ + return (struct radeon_drm_cs*)base; +} + +static INLINE boolean radeon_bo_is_referenced_by_cs(struct radeon_drm_cs *cs, + struct radeon_bo *bo) +{ + return bo->num_cs_references == bo->rws->num_cs || + (bo->num_cs_references && radeon_get_reloc(cs->csc, bo) != -1); +} + +static INLINE boolean radeon_bo_is_referenced_by_any_cs(struct radeon_bo *bo) +{ + return bo->num_cs_references; +} + +void radeon_drm_cs_sync_flush(struct radeon_drm_cs *cs); +void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws); + +#endif diff --git a/src/gallium/winsys/radeon/drm/radeon_r300.c b/src/gallium/winsys/radeon/drm/radeon_r300.c deleted file mode 100644 index 9f59b3de46..0000000000 --- a/src/gallium/winsys/radeon/drm/radeon_r300.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "radeon_drm_buffer.h" - -#include "util/u_memory.h" -#include "pipebuffer/pb_bufmgr.h" - -#include "radeon_cs_gem.h" -#include "state_tracker/drm_driver.h" - -static unsigned get_pb_usage_from_create_flags(unsigned bind, unsigned usage, - enum r300_buffer_domain domain) -{ - unsigned res = 0; - - if (bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT)) - res |= PB_USAGE_GPU_WRITE; - - if (bind & PIPE_BIND_SAMPLER_VIEW) - res |= PB_USAGE_GPU_READ | PB_USAGE_GPU_WRITE; - - if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) - res |= PB_USAGE_GPU_READ; - - if (bind & PIPE_BIND_TRANSFER_WRITE) - res |= PB_USAGE_CPU_WRITE; - - if (bind & PIPE_BIND_TRANSFER_READ) - res |= PB_USAGE_CPU_READ; - - /* Is usage of any use for us? Probably not. */ - - /* Now add driver-specific usage flags. */ - if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) - res |= RADEON_PB_USAGE_VERTEX; - - if (domain & R300_DOMAIN_GTT) - res |= RADEON_PB_USAGE_DOMAIN_GTT; - - if (domain & R300_DOMAIN_VRAM) - res |= RADEON_PB_USAGE_DOMAIN_VRAM; - - return res; -} - -static struct r300_winsys_buffer * -radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws, - unsigned size, - unsigned alignment, - unsigned bind, - unsigned usage, - enum r300_buffer_domain domain) -{ - struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); - struct pb_desc desc; - struct pb_manager *provider; - struct pb_buffer *buffer; - - memset(&desc, 0, sizeof(desc)); - desc.alignment = alignment; - desc.usage = get_pb_usage_from_create_flags(bind, usage, domain); - - /* Assign a buffer manager. */ - if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) - provider = ws->cman; - else - provider = ws->kman; - - buffer = provider->create_buffer(provider, size, &desc); - if (!buffer) - return NULL; - - return (struct r300_winsys_buffer*)buffer; -} - -static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws, - struct r300_winsys_buffer **pdst, - struct r300_winsys_buffer *src) -{ - struct pb_buffer *_src = radeon_pb_buffer(src); - struct pb_buffer *_dst = radeon_pb_buffer(*pdst); - - pb_reference(&_dst, _src); - - *pdst = (struct r300_winsys_buffer*)_dst; -} - -static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws, - struct winsys_handle *whandle, - unsigned *stride, - unsigned *size) -{ - struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); - struct pb_buffer *_buf; - - _buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle); - - if (stride) - *stride = whandle->stride; - if (size) - *size = _buf->base.size; - - return (struct r300_winsys_buffer*)_buf; -} - -static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws, - struct r300_winsys_buffer *buffer, - unsigned stride, - struct winsys_handle *whandle) -{ - struct pb_buffer *_buf = radeon_pb_buffer(buffer); - whandle->stride = stride; - return radeon_drm_bufmgr_get_handle(_buf, whandle); -} - -static void radeon_r300_winsys_cs_set_flush(struct r300_winsys_cs *rcs, - void (*flush)(void *), - void *user) -{ - struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - cs->flush_cs = flush; - cs->flush_data = user; - radeon_cs_space_set_flush(cs->cs, flush, user); -} - -static boolean radeon_r300_winsys_cs_validate(struct r300_winsys_cs *rcs) -{ - struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - - return radeon_cs_space_check(cs->cs) >= 0; -} - -static void radeon_r300_winsys_cs_reset_buffers(struct r300_winsys_cs *rcs) -{ - struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - radeon_cs_space_reset_bos(cs->cs); -} - -static void radeon_r300_winsys_cs_flush(struct r300_winsys_cs *rcs) -{ - struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - int retval; - - /* Don't flush a zero-sized CS. */ - if (!cs->base.cdw) { - return; - } - - cs->cs->cdw = cs->base.cdw; - - radeon_drm_bufmgr_flush_maps(cs->ws->kman); - - /* Emit the CS. */ - retval = radeon_cs_emit(cs->cs); - if (retval) { - if (debug_get_bool_option("RADEON_DUMP_CS", FALSE)) { - fprintf(stderr, "radeon: The kernel rejected CS, dumping...\n"); - radeon_cs_print(cs->cs, stderr); - } else { - fprintf(stderr, "radeon: The kernel rejected CS, " - "see dmesg for more information.\n"); - } - } - - /* Reset CS. - * Someday, when we care about performance, we should really find a way - * to rotate between two or three CS objects so that the GPU can be - * spinning through one CS while another one is being filled. */ - radeon_cs_erase(cs->cs); - - cs->base.buf = cs->cs->packets; - cs->base.cdw = cs->cs->cdw; -} - -static uint32_t radeon_get_value(struct r300_winsys_screen *rws, - enum r300_value_id id) -{ - struct radeon_drm_winsys *ws = (struct radeon_drm_winsys *)rws; - - switch(id) { - case R300_VID_PCI_ID: - return ws->pci_id; - case R300_VID_GB_PIPES: - return ws->gb_pipes; - case R300_VID_Z_PIPES: - return ws->z_pipes; - case R300_VID_SQUARE_TILING_SUPPORT: - return ws->squaretiling; - case R300_VID_DRM_2_3_0: - return ws->drm_2_3_0; - case R300_VID_DRM_2_6_0: - return ws->drm_2_6_0; - case R300_CAN_HYPERZ: - return ws->hyperz; - } - return 0; -} - -static struct r300_winsys_cs *radeon_r300_winsys_cs_create(struct r300_winsys_screen *rws) -{ - struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); - struct radeon_drm_cs *cs = CALLOC_STRUCT(radeon_drm_cs); - - if (!cs) - return NULL; - - /* Size limit on IBs is 64 kibibytes. */ - cs->cs = radeon_cs_create(ws->csm, 1024 * 64 / 4); - if (!cs->cs) { - FREE(cs); - return NULL; - } - - radeon_cs_set_limit(cs->cs, - RADEON_GEM_DOMAIN_GTT, ws->gart_size); - radeon_cs_set_limit(cs->cs, - RADEON_GEM_DOMAIN_VRAM, ws->vram_size); - - cs->ws = ws; - cs->base.buf = cs->cs->packets; - cs->base.cdw = cs->cs->cdw; - return &cs->base; -} - -static void radeon_r300_winsys_cs_destroy(struct r300_winsys_cs *rcs) -{ - struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - radeon_cs_destroy(cs->cs); - FREE(cs); -} - -void radeon_winsys_init_functions(struct radeon_drm_winsys *ws) -{ - ws->base.get_value = radeon_get_value; - ws->base.buffer_create = radeon_r300_winsys_buffer_create; - ws->base.buffer_reference = radeon_r300_winsys_buffer_reference; - ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle; - ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle; - ws->base.cs_create = radeon_r300_winsys_cs_create; - ws->base.cs_destroy = radeon_r300_winsys_cs_destroy; - ws->base.cs_validate = radeon_r300_winsys_cs_validate; - ws->base.cs_flush = radeon_r300_winsys_cs_flush; - ws->base.cs_reset_buffers = radeon_r300_winsys_cs_reset_buffers; - ws->base.cs_set_flush = radeon_r300_winsys_cs_set_flush; -} diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h index 81da1a25e0..9ecbb07457 100644 --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h @@ -36,8 +36,8 @@ struct radeon_drm_winsys { struct r300_winsys_screen base; int fd; /* DRM file descriptor */ + int num_cs; /* The number of command streams created. */ - struct radeon_bo_manager *bom; /* Radeon BO manager. */ struct pb_manager *kman; struct pb_manager *cman; @@ -46,44 +46,22 @@ struct radeon_drm_winsys { uint32_t z_pipes; /* Z pipe count (rv530 only) */ uint32_t gart_size; /* GART size. */ uint32_t vram_size; /* VRAM size. */ - boolean squaretiling; /* Square tiling support. */ - /* DRM 2.3.0 (R500 VAP regs, MSPOS regs, fixed tex3D size checking) */ - boolean drm_2_3_0; - /* DRM 2.6.0 (Hyper-Z, GB_Z_PEQ_CONFIG allowed on rv350->r4xx) */ - boolean drm_2_6_0; - /* Hyper-Z user */ - boolean hyperz; - - /* Radeon CS manager. */ - struct radeon_cs_manager *csm; -}; - -struct radeon_drm_cs { - struct r300_winsys_cs base; - - /* The winsys. */ - struct radeon_drm_winsys *ws; + uint32_t num_cpus; /* Number of CPUs. */ - /* The libdrm command stream. */ - struct radeon_cs *cs; + unsigned drm_major; + unsigned drm_minor; + unsigned drm_patchlevel; - /* Flush CS. */ - void (*flush_cs)(void *); - void *flush_data; + /* Hyper-Z user */ + boolean hyperz; + /* AA compression (CMask) */ + boolean aacompress; }; -static INLINE struct radeon_drm_cs * -radeon_drm_cs(struct r300_winsys_cs *base) -{ - return (struct radeon_drm_cs*)base; -} - static INLINE struct radeon_drm_winsys * radeon_drm_winsys(struct r300_winsys_screen *base) { return (struct radeon_drm_winsys*)base; } -void radeon_winsys_init_functions(struct radeon_drm_winsys *ws); - #endif diff --git a/src/gallium/winsys/svga/drm/vmw_buffer.c b/src/gallium/winsys/svga/drm/vmw_buffer.c index eca174a6c5..80d5dfc3ed 100644 --- a/src/gallium/winsys/svga/drm/vmw_buffer.c +++ b/src/gallium/winsys/svga/drm/vmw_buffer.c @@ -120,7 +120,8 @@ vmw_gmr_buffer_destroy(struct pb_buffer *_buf) static void * vmw_gmr_buffer_map(struct pb_buffer *_buf, - unsigned flags) + unsigned flags, + void *flush_ctx) { struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf); return buf->map; diff --git a/src/gallium/winsys/svga/drm/vmw_context.c b/src/gallium/winsys/svga/drm/vmw_context.c index 11626ee637..f2124c1bf6 100644 --- a/src/gallium/winsys/svga/drm/vmw_context.c +++ b/src/gallium/winsys/svga/drm/vmw_context.c @@ -320,7 +320,7 @@ vmw_swc_region_relocation(struct svga_winsys_context *swc, * to the FIFO won't cause flushing in the host. */ vswc->seen_regions += reloc->buffer->base.size; - if(vswc->seen_regions >= VMW_GMR_POOL_SIZE/2) + if(vswc->seen_regions >= VMW_GMR_POOL_SIZE/3) vswc->preemptive_flush = TRUE; } diff --git a/src/gallium/winsys/svga/drm/vmw_screen.c b/src/gallium/winsys/svga/drm/vmw_screen.c index 51a4c55e5a..cc3003d252 100644 --- a/src/gallium/winsys/svga/drm/vmw_screen.c +++ b/src/gallium/winsys/svga/drm/vmw_screen.c @@ -45,8 +45,6 @@ vmw_winsys_create( int fd, boolean use_old_scanout_flag ) vws->ioctl.drm_fd = fd; vws->use_old_scanout_flag = use_old_scanout_flag; - debug_printf("%s: use_old_scanout_flag == %s\n", __FUNCTION__, - use_old_scanout_flag ? "true" : "false"); if (!vmw_ioctl_init(vws)) goto out_no_ioctl; diff --git a/src/gallium/winsys/sw/dri/SConscript b/src/gallium/winsys/sw/dri/SConscript index b255d725f9..f8e1fa6cfd 100644 --- a/src/gallium/winsys/sw/dri/SConscript +++ b/src/gallium/winsys/sw/dri/SConscript @@ -4,7 +4,7 @@ Import('*') -if env['platform'] == 'linux': +if env['platform'] in ('linux', 'sunos'): env = env.Clone() diff --git a/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c b/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c index 8f9a90858d..51245766d1 100644 --- a/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c +++ b/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c @@ -61,10 +61,8 @@ struct wrapper_sw_displaytarget struct pipe_resource *tex; struct pipe_transfer *transfer; - unsigned width; - unsigned height; unsigned map_count; - unsigned stride; /**< because we give stride at create */ + unsigned stride; /**< because we get stride at create */ void *ptr; }; @@ -95,7 +93,7 @@ wsw_dt_get_stride(struct wrapper_sw_displaytarget *wdt, unsigned *stride) tr = pipe_get_transfer(pipe, tex, 0, 0, PIPE_TRANSFER_READ_WRITE, - 0, 0, wdt->width, wdt->height); + 0, 0, wdt->tex->width0, wdt->tex->height0); if (!tr) return FALSE; @@ -208,7 +206,7 @@ wsw_dt_map(struct sw_winsys *ws, tr = pipe_get_transfer(pipe, tex, 0, 0, PIPE_TRANSFER_READ_WRITE, - 0, 0, wdt->width, wdt->height); + 0, 0, wdt->tex->width0, wdt->tex->height0); if (!tr) return NULL; @@ -248,6 +246,7 @@ wsw_dt_unmap(struct sw_winsys *ws, pipe->transfer_unmap(pipe, wdt->transfer); pipe->transfer_destroy(pipe, wdt->transfer); + pipe->flush(pipe, NULL); wdt->transfer = NULL; } diff --git a/src/gallium/winsys/sw/xlib/SConscript b/src/gallium/winsys/sw/xlib/SConscript index df01a9ec2b..e9c274059b 100644 --- a/src/gallium/winsys/sw/xlib/SConscript +++ b/src/gallium/winsys/sw/xlib/SConscript @@ -4,7 +4,7 @@ Import('*') -if env['platform'] in ('cygwin', 'linux'): +if env['platform'] in ('cygwin', 'linux', 'sunos'): env = env.Clone() |