diff options
Diffstat (limited to 'src/gallium/winsys/drm')
65 files changed, 7204 insertions, 279 deletions
diff --git a/src/gallium/winsys/drm/SConscript b/src/gallium/winsys/drm/SConscript index a9e9f2682a7..66b73a8bf93 100644 --- a/src/gallium/winsys/drm/SConscript +++ b/src/gallium/winsys/drm/SConscript @@ -48,11 +48,21 @@ if env['dri']: # $(INSTALL) -d $(DRI_DRIVER_INSTALL_DIR) # $(INSTALL) -m 755 $(LIBNAME) $(DRI_DRIVER_INSTALL_DIR) + if 'vmware' in env['winsys']: + SConscript([ + 'vmware/SConscript', + ]) + if 'intel' in env['winsys']: SConscript([ 'intel/SConscript', ]) + if 'i965' in env['winsys']: + SConscript([ + 'i965/SConscript', + ]) + if 'radeon' in env['winsys']: SConscript([ 'radeon/SConscript', diff --git a/src/gallium/winsys/drm/i965/Makefile b/src/gallium/winsys/drm/i965/Makefile new file mode 100644 index 00000000000..d8feef6824a --- /dev/null +++ b/src/gallium/winsys/drm/i965/Makefile @@ -0,0 +1,12 @@ +# src/gallium/winsys/drm/intel/Makefile +TOP = ../../../../.. +include $(TOP)/configs/current + +SUBDIRS = gem $(GALLIUM_STATE_TRACKERS_DIRS) + +default install clean: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE) $@) || exit 1; \ + fi \ + done diff --git a/src/gallium/winsys/drm/i965/SConscript b/src/gallium/winsys/drm/i965/SConscript new file mode 100644 index 00000000000..50d7b75ed68 --- /dev/null +++ b/src/gallium/winsys/drm/i965/SConscript @@ -0,0 +1,7 @@ +Import('*') + +SConscript(['gem/SConscript',]) + +if 'mesa' in env['statetrackers']: + + SConscript(['dri/SConscript']) diff --git a/src/gallium/winsys/drm/i965/dri/Makefile b/src/gallium/winsys/drm/i965/dri/Makefile new file mode 100644 index 00000000000..f7e81eed87b --- /dev/null +++ b/src/gallium/winsys/drm/i965/dri/Makefile @@ -0,0 +1,26 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBNAME = i965_dri.so + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ + $(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/identity/libidentity.a \ + $(TOP)/src/gallium/drivers/i965/libi965.a + + +DRIVER_SOURCES = + +C_SOURCES = \ + $(COMMON_GALLIUM_SOURCES) \ + $(DRIVER_SOURCES) + +include ../../Makefile.template + +DRI_LIB_DEPS += -ldrm_intel + +symlinks: $(TOP)/$(LIB_DIR)/gallium + @rm -f $(TOP)/$(LIB_DIR)/gallium/i965_dri.so diff --git a/src/gallium/winsys/drm/i965/dri/SConscript b/src/gallium/winsys/drm/i965/dri/SConscript new file mode 100644 index 00000000000..a99533fd245 --- /dev/null +++ b/src/gallium/winsys/drm/i965/dri/SConscript @@ -0,0 +1,19 @@ +Import('*') + +env = drienv.Clone() + +env.ParseConfig('pkg-config --cflags --libs libdrm_intel') + +drivers = [ + st_dri, + i965drm, + i965, + trace, +] + +env.LoadableModule( + target ='i965_dri.so', + source = COMMON_GALLIUM_SOURCES, + LIBS = drivers + mesa + gallium + env['LIBS'], + SHLIBPREFIX = '', +) diff --git a/src/gallium/winsys/drm/i965/egl/Makefile b/src/gallium/winsys/drm/i965/egl/Makefile new file mode 100644 index 00000000000..a1b32eb2a79 --- /dev/null +++ b/src/gallium/winsys/drm/i965/egl/Makefile @@ -0,0 +1,29 @@ +TOP = ../../../../../.. +GALLIUMDIR = ../../../.. +include $(TOP)/configs/current + +LIBNAME = EGL_i965.so + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ + $(GALLIUMDIR)/winsys/drm/i965/gem/libi965drm.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/i965/libi965.a + +DRIVER_SOURCES = + +C_SOURCES = \ + $(COMMON_GALLIUM_SOURCES) \ + $(DRIVER_SOURCES) + +DRIVER_EXTRAS = -ldrm_intel + +ASM_SOURCES = + +DRIVER_DEFINES = -I../gem $(shell pkg-config libdrm --atleast-version=2.3.1 \ + && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP") + +include ../../Makefile.template + +symlinks: diff --git a/src/gallium/winsys/drm/i965/gem/Makefile b/src/gallium/winsys/drm/i965/gem/Makefile new file mode 100644 index 00000000000..6a7497b6be3 --- /dev/null +++ b/src/gallium/winsys/drm/i965/gem/Makefile @@ -0,0 +1,14 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBNAME = i965drm + +C_SOURCES = \ + i965_drm_buffer.c \ + i965_drm_api.c + +LIBRARY_INCLUDES = $(shell pkg-config libdrm --cflags-only-I) + +LIBRARY_DEFINES = $(shell pkg-config libdrm --cflags-only-other) + +include ../../../../Makefile.template diff --git a/src/gallium/winsys/drm/i965/gem/SConscript b/src/gallium/winsys/drm/i965/gem/SConscript new file mode 100644 index 00000000000..6256ec6eaf0 --- /dev/null +++ b/src/gallium/winsys/drm/i965/gem/SConscript @@ -0,0 +1,15 @@ +Import('*') + +env = drienv.Clone() + +i965drm_sources = [ + 'i965_drm_api.c', + 'i965_drm_buffer.c', +] + +i965drm = env.ConvenienceLibrary( + target ='i965drm', + source = i965drm_sources, +) + +Export('i965drm') diff --git a/src/gallium/winsys/drm/i965/gem/i965_drm_api.c b/src/gallium/winsys/drm/i965/gem/i965_drm_api.c new file mode 100644 index 00000000000..fc9678d2b62 --- /dev/null +++ b/src/gallium/winsys/drm/i965/gem/i965_drm_api.c @@ -0,0 +1,243 @@ + +#include <stdio.h> +#include "state_tracker/drm_api.h" + +#include "i965_drm_winsys.h" +#include "util/u_memory.h" + +#include "i965/brw_context.h" /* XXX: shouldn't be doing this */ +#include "i965/brw_screen.h" /* XXX: shouldn't be doing this */ + +#include "trace/tr_drm.h" + +/* + * Helper functions + */ + + +static void +i965_libdrm_get_device_id(unsigned int *device_id) +{ + char path[512]; + FILE *file; + void *shutup_gcc; + + /* + * FIXME: Fix this up to use a drm ioctl or whatever. + */ + + snprintf(path, sizeof(path), "/sys/class/drm/card0/device/device"); + file = fopen(path, "r"); + if (!file) { + return; + } + + shutup_gcc = fgets(path, sizeof(path), file); + sscanf(path, "%x", device_id); + fclose(file); +} + +static struct i965_libdrm_buffer * +i965_libdrm_buffer_from_handle(struct i965_libdrm_winsys *idws, + const char* name, unsigned handle) +{ + struct i965_libdrm_buffer *buf = CALLOC_STRUCT(i965_libdrm_buffer); + uint32_t swizzle = 0; + + if (BRW_DUMP) + debug_printf("%s\n", __FUNCTION__); + + if (!buf) + return NULL; + pipe_reference_init(&buf->base.reference, 1); + buf->bo = drm_intel_bo_gem_create_from_name(idws->gem, name, handle); + buf->base.size = buf->bo->size; + buf->base.sws = &idws->base; + buf->flinked = TRUE; + buf->flink = handle; + + + if (!buf->bo) + goto err; + + drm_intel_bo_get_tiling(buf->bo, &buf->tiling, &swizzle); + if (buf->tiling != 0) + buf->map_gtt = TRUE; + + return buf; + +err: + FREE(buf); + return NULL; +} + + +/* + * Exported functions + */ + + +static struct pipe_texture * +i965_libdrm_texture_from_shared_handle(struct drm_api *api, + struct pipe_screen *screen, + struct pipe_texture *template, + const char* name, + unsigned pitch, + unsigned handle) +{ + /* XXX: this is silly -- there should be a way to get directly from + * the "drm_api" struct to ourselves, without peering into + * unrelated code: + */ + struct i965_libdrm_winsys *idws = i965_libdrm_winsys(brw_screen(screen)->sws); + struct i965_libdrm_buffer *buffer; + + if (BRW_DUMP) + debug_printf("%s %s pitch %d handle 0x%x\n", __FUNCTION__, + name, pitch, handle); + + buffer = i965_libdrm_buffer_from_handle(idws, name, handle); + if (!buffer) + return NULL; + + return brw_texture_blanket_winsys_buffer(screen, template, pitch, + buffer->tiling, + &buffer->base); +} + + +static boolean +i965_libdrm_shared_handle_from_texture(struct drm_api *api, + struct pipe_screen *screen, + struct pipe_texture *texture, + unsigned *pitch, + unsigned *handle) +{ + struct i965_libdrm_buffer *buf = NULL; + struct brw_winsys_buffer *buffer = NULL; + + if (BRW_DUMP) + debug_printf("%s\n", __FUNCTION__); + + if (!brw_texture_get_winsys_buffer(texture, &buffer, pitch)) + return FALSE; + + buf = i965_libdrm_buffer(buffer); + if (!buf->flinked) { + if (drm_intel_bo_flink(buf->bo, &buf->flink)) + return FALSE; + buf->flinked = TRUE; + } + + *handle = buf->flink; + + if (BRW_DUMP) + debug_printf(" -> pitch %d handle 0x%x\n", *pitch, *handle); + + return TRUE; +} + +static boolean +i965_libdrm_local_handle_from_texture(struct drm_api *api, + struct pipe_screen *screen, + struct pipe_texture *texture, + unsigned *pitch, + unsigned *handle) +{ + struct brw_winsys_buffer *buffer = NULL; + + if (BRW_DUMP) + debug_printf("%s\n", __FUNCTION__); + + if (!brw_texture_get_winsys_buffer(texture, &buffer, pitch)) + return FALSE; + + *handle = i965_libdrm_buffer(buffer)->bo->handle; + + if (BRW_DUMP) + debug_printf(" -> pitch %d handle 0x%x\n", *pitch, *handle); + + return TRUE; +} + +static void +i965_libdrm_winsys_destroy(struct brw_winsys_screen *iws) +{ + struct i965_libdrm_winsys *idws = i965_libdrm_winsys(iws); + + if (BRW_DUMP) + debug_printf("%s\n", __FUNCTION__); + + drm_intel_bufmgr_destroy(idws->gem); + + FREE(idws); +} + +static struct pipe_screen * +i965_libdrm_create_screen(struct drm_api *api, int drmFD, + struct drm_create_screen_arg *arg) +{ + struct i965_libdrm_winsys *idws; + unsigned int deviceID; + + debug_printf("%s\n", __FUNCTION__); + + if (arg != NULL) { + switch(arg->mode) { + case DRM_CREATE_NORMAL: + break; + default: + return NULL; + } + } + + idws = CALLOC_STRUCT(i965_libdrm_winsys); + if (!idws) + return NULL; + + i965_libdrm_get_device_id(&deviceID); + + i965_libdrm_winsys_init_buffer_functions(idws); + + idws->fd = drmFD; + idws->id = deviceID; + + idws->base.destroy = i965_libdrm_winsys_destroy; + + idws->gem = drm_intel_bufmgr_gem_init(idws->fd, BRW_BATCH_SIZE); + drm_intel_bufmgr_gem_enable_reuse(idws->gem); + + idws->send_cmd = !debug_get_bool_option("BRW_NO_HW", FALSE); + + return brw_create_screen(&idws->base, deviceID); +} + +static struct pipe_context * +i965_libdrm_create_context(struct drm_api *api, struct pipe_screen *screen) +{ + return brw_create_context(screen); +} + +static void +destroy(struct drm_api *api) +{ + if (BRW_DUMP) + debug_printf("%s\n", __FUNCTION__); + +} + +struct drm_api i965_libdrm_api = +{ + .create_context = i965_libdrm_create_context, + .create_screen = i965_libdrm_create_screen, + .texture_from_shared_handle = i965_libdrm_texture_from_shared_handle, + .shared_handle_from_texture = i965_libdrm_shared_handle_from_texture, + .local_handle_from_texture = i965_libdrm_local_handle_from_texture, + .destroy = destroy, +}; + +struct drm_api * +drm_api_create() +{ + return trace_drm_create(&i965_libdrm_api); +} diff --git a/src/gallium/winsys/drm/i965/gem/i965_drm_buffer.c b/src/gallium/winsys/drm/i965/gem/i965_drm_buffer.c new file mode 100644 index 00000000000..a4a72b372dd --- /dev/null +++ b/src/gallium/winsys/drm/i965/gem/i965_drm_buffer.c @@ -0,0 +1,427 @@ + +#include "i965_drm_winsys.h" +#include "util/u_memory.h" + +#include "i915_drm.h" +#include "intel_bufmgr.h" + + + +const char *names[BRW_BUFFER_TYPE_MAX] = { + "TEXTURE", + "SCANOUT", + "VERTEX", + "CURBE", + "QUERY", + "SHADER_CONSTANTS", + "WM_SCRATCH", + "BATCH", + "GENERAL_STATE", + "SURFACE_STATE", + "PIXEL", + "GENERIC", +}; + +const char *usages[BRW_USAGE_MAX] = { + "STATE", + "QUERY_RESULT", + "RENDER_TARGET", + "DEPTH_BUFFER", + "BLIT_SOURCE", + "BLIT_DEST", + "SAMPLER", + "VERTEX", + "SCRATCH" +}; + + +const char *data_types[BRW_DATA_MAX] = +{ + "GS: CC_VP", + "GS: CC_UNIT", + "GS: WM_PROG", + "GS: SAMPLER_DEFAULT_COLOR", + "GS: SAMPLER", + "GS: WM_UNIT", + "GS: SF_PROG", + "GS: SF_VP", + "GS: SF_UNIT", + "GS: VS_UNIT", + "GS: VS_PROG", + "GS: GS_UNIT", + "GS: GS_PROG", + "GS: CLIP_VP", + "GS: CLIP_UNIT", + "GS: CLIP_PROG", + "SS: SURFACE", + "SS: SURF_BIND", + "CONSTANT DATA", + "BATCH DATA", + "(untyped)" +}; + +static enum pipe_error +i965_libdrm_bo_alloc(struct brw_winsys_screen *sws, + enum brw_buffer_type type, + unsigned size, + unsigned alignment, + struct brw_winsys_buffer **bo_out) +{ + struct i965_libdrm_winsys *idws = i965_libdrm_winsys(sws); + struct i965_libdrm_buffer *buf; + + if (BRW_DUMP) + debug_printf("%s type %s sz %d align %d\n", + __FUNCTION__, names[type], size, alignment ); + + buf = CALLOC_STRUCT(i965_libdrm_buffer); + if (!buf) + return PIPE_ERROR_OUT_OF_MEMORY; + + switch (type) { + case BRW_BUFFER_TYPE_TEXTURE: +/* case BRW_BUFFER_TYPE_SCANOUT:*/ + case BRW_BUFFER_TYPE_VERTEX: + case BRW_BUFFER_TYPE_CURBE: + case BRW_BUFFER_TYPE_QUERY: + case BRW_BUFFER_TYPE_SHADER_CONSTANTS: + case BRW_BUFFER_TYPE_SHADER_SCRATCH: + case BRW_BUFFER_TYPE_BATCH: + case BRW_BUFFER_TYPE_GENERAL_STATE: + case BRW_BUFFER_TYPE_SURFACE_STATE: + case BRW_BUFFER_TYPE_PIXEL: + case BRW_BUFFER_TYPE_GENERIC: + break; + case BRW_BUFFER_TYPE_SCANOUT: + buf->map_gtt = TRUE; + break; + default: + assert(0); + break; + } + + buf->bo = drm_intel_bo_alloc(idws->gem, + names[type], + size, + alignment); + + if (!buf->bo) + goto err; + + pipe_reference_init(&buf->base.reference, 1); + buf->base.size = size; + buf->base.sws = sws; + + *bo_out = &buf->base; + return PIPE_OK; + +err: + assert(0); + FREE(buf); + return PIPE_ERROR_OUT_OF_MEMORY; +} + +static void +i965_libdrm_bo_destroy(struct brw_winsys_buffer *buffer) +{ + struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); + + if (BRW_DUMP) + debug_printf("%s\n", __FUNCTION__); + + drm_intel_bo_unreference(buf->bo); + FREE(buffer); +} + +static enum pipe_error +i965_libdrm_bo_emit_reloc(struct brw_winsys_buffer *buffer, + enum brw_buffer_usage usage, + unsigned delta, + unsigned offset, + struct brw_winsys_buffer *buffer2) +{ + struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); + struct i965_libdrm_buffer *buf2 = i965_libdrm_buffer(buffer2); + int read, write; + int ret; + + if (BRW_DUMP) + debug_printf("%s buf %p offset %x delta %x buf2 %p/%s/%s\n", + __FUNCTION__, (void *)buffer, + offset, delta, + (void *)buffer2, names[buf2->data_type], usages[usage]); + + switch (usage) { + case BRW_USAGE_STATE: + read = I915_GEM_DOMAIN_INSTRUCTION; + write = 0; + break; + case BRW_USAGE_QUERY_RESULT: + read = I915_GEM_DOMAIN_INSTRUCTION; + write = I915_GEM_DOMAIN_INSTRUCTION; + break; + case BRW_USAGE_RENDER_TARGET: + read = I915_GEM_DOMAIN_RENDER; + write = 0; + break; + case BRW_USAGE_DEPTH_BUFFER: + read = I915_GEM_DOMAIN_RENDER; + write = I915_GEM_DOMAIN_RENDER; + break; + case BRW_USAGE_BLIT_SOURCE: + read = 0; + write = I915_GEM_DOMAIN_RENDER; + break; + case BRW_USAGE_BLIT_DEST: + read = I915_GEM_DOMAIN_RENDER; + write = I915_GEM_DOMAIN_RENDER; + break; + case BRW_USAGE_SAMPLER: + read = I915_GEM_DOMAIN_SAMPLER; + write = 0; + break; + case BRW_USAGE_VERTEX: + read = I915_GEM_DOMAIN_VERTEX; + write = 0; + break; + case BRW_USAGE_SCRATCH: + read = 0; + write = 0; + break; + default: + assert(0); + return -1; + } + + /* Needed?? + ((uint32_t *)buf->bo->virtual)[offset/4] = (delta + + buf2->bo->offset); + */ + + ret = dri_bo_emit_reloc( buf->bo, read, write, delta, offset, buf2->bo ); + if (ret) + return -1; + + return 0; +} + +static enum pipe_error +i965_libdrm_bo_exec(struct brw_winsys_buffer *buffer, + unsigned bytes_used) +{ + struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); + struct i965_libdrm_winsys *idws = i965_libdrm_winsys(buffer->sws); + int ret; + + if (BRW_DUMP) + debug_printf("execute buffer %p, bytes %d\n", (void *)buffer, bytes_used); + + if (idws->send_cmd) { + ret = dri_bo_exec(buf->bo, bytes_used, NULL, 0, 0); + if (ret) + return PIPE_ERROR; + } + + return PIPE_OK; +} + +static enum pipe_error +i965_libdrm_bo_subdata(struct brw_winsys_buffer *buffer, + enum brw_buffer_data_type data_type, + size_t offset, + size_t size, + const void *data, + const struct brw_winsys_reloc *reloc, + unsigned nr_reloc) +{ + struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); + struct i965_libdrm_winsys *idws = i965_libdrm_winsys(buffer->sws); + int ret, i; + + (void)data_type; + + if (BRW_DUMP) + debug_printf("%s buf %p off %d sz %d %s relocs: %d\n", + __FUNCTION__, + (void *)buffer, offset, size, + data_types[data_type], + nr_reloc); + + if (BRW_DUMP) + brw_dump_data( idws->id, + data_type, + buf->bo->offset + offset, + data, size ); + + /* XXX: use bo_map_gtt/memcpy/unmap_gtt under some circumstances??? + */ + ret = drm_intel_bo_subdata(buf->bo, offset, size, (void*)data); + if (ret) + return PIPE_ERROR; + + for (i = 0; i < nr_reloc; i++) { + i965_libdrm_bo_emit_reloc(buffer, reloc[i].usage, reloc[i].delta, + reloc[i].offset, reloc[i].bo); + } + + return PIPE_OK; +} + +static boolean +i965_libdrm_bo_is_busy(struct brw_winsys_buffer *buffer) +{ + struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); + boolean ret; + + if (BRW_DUMP) + debug_printf("%s %p\n", __FUNCTION__, (void *)buffer); + + ret = drm_intel_bo_busy(buf->bo); + + if (BRW_DUMP) + debug_printf(" --> %d\n", ret); + + return ret; +} + +static boolean +i965_libdrm_bo_references(struct brw_winsys_buffer *a, + struct brw_winsys_buffer *b) +{ + struct i965_libdrm_buffer *bufa = i965_libdrm_buffer(a); + struct i965_libdrm_buffer *bufb = i965_libdrm_buffer(b); + boolean ret; + + if (BRW_DUMP) + debug_printf("%s %p %p\n", __FUNCTION__, (void *)a, (void *)b); + + ret = drm_intel_bo_references(bufa->bo, bufb->bo); + + if (BRW_DUMP) + debug_printf(" --> %d\n", ret); + + return ret; +} + +/* XXX: couldn't this be handled by returning true/false on + * bo_emit_reloc? + */ +static enum pipe_error +i965_libdrm_check_aperture_space(struct brw_winsys_screen *iws, + struct brw_winsys_buffer **buffers, + unsigned count) +{ + static drm_intel_bo *bos[128]; + int i; + int ret; + + if (BRW_DUMP) + debug_printf("%s\n", __FUNCTION__); + + if (count > Elements(bos)) { + assert(0); + return FALSE; + } + + for (i = 0; i < count; i++) + bos[i] = i965_libdrm_buffer(buffers[i])->bo; + + /* XXX: converting from ??? to pipe_error: + */ + ret = dri_bufmgr_check_aperture_space(bos, count); + + if (BRW_DUMP) + debug_printf(" --> %d (ok == %d)\n", ret, PIPE_OK); + + return ret; +} + +static void * +i965_libdrm_bo_map(struct brw_winsys_buffer *buffer, + enum brw_buffer_data_type data_type, + unsigned offset, + unsigned length, + boolean write, + boolean discard, + boolean flush_explicit) +{ + struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); + int ret; + + + if (BRW_DUMP) + debug_printf("%s %p %s %s\n", __FUNCTION__, (void *)buffer, + write ? "read/write" : "read", + write ? data_types[data_type] : ""); + + if (!buf->map_count) { + if (buf->map_gtt) { + ret = drm_intel_gem_bo_map_gtt(buf->bo); + if (ret) + return NULL; + } + else { + ret = drm_intel_bo_map(buf->bo, write); + if (ret) + return NULL; + } + } + + buf->data_type = data_type; + buf->map_count++; + return buf->bo->virtual; +} + +static void +i965_libdrm_bo_flush_range(struct brw_winsys_buffer *buffer, + unsigned offset, + unsigned length) +{ + struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); + struct i965_libdrm_winsys *idws = i965_libdrm_winsys(buffer->sws); + + if (BRW_DUMP) + debug_printf("%s %s offset %d len %d\n", __FUNCTION__, + data_types[buf->data_type], + offset, length); + + if (BRW_DUMP) + brw_dump_data( idws->id, + buf->data_type, + buf->bo->offset + offset, + buf->bo->virtual + offset, + length ); +} + +static void +i965_libdrm_bo_unmap(struct brw_winsys_buffer *buffer) +{ + struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); + + if (BRW_DUMP) + debug_printf("%s\n", __FUNCTION__); + + if (--buf->map_count > 0) + return; + + if (buf->map_gtt) + drm_intel_gem_bo_unmap_gtt(buf->bo); + else + drm_intel_bo_unmap(buf->bo); +} + +void +i965_libdrm_winsys_init_buffer_functions(struct i965_libdrm_winsys *idws) +{ + idws->base.bo_alloc = i965_libdrm_bo_alloc; + idws->base.bo_destroy = i965_libdrm_bo_destroy; + idws->base.bo_emit_reloc = i965_libdrm_bo_emit_reloc; + idws->base.bo_exec = i965_libdrm_bo_exec; + idws->base.bo_subdata = i965_libdrm_bo_subdata; + idws->base.bo_is_busy = i965_libdrm_bo_is_busy; + idws->base.bo_references = i965_libdrm_bo_references; + idws->base.check_aperture_space = i965_libdrm_check_aperture_space; + idws->base.bo_map = i965_libdrm_bo_map; + idws->base.bo_flush_range = i965_libdrm_bo_flush_range; + idws->base.bo_unmap = i965_libdrm_bo_unmap; +} diff --git a/src/gallium/winsys/drm/i965/gem/i965_drm_winsys.h b/src/gallium/winsys/drm/i965/gem/i965_drm_winsys.h new file mode 100644 index 00000000000..c6a7d4a8c51 --- /dev/null +++ b/src/gallium/winsys/drm/i965/gem/i965_drm_winsys.h @@ -0,0 +1,64 @@ + +#ifndef INTEL_DRM_WINSYS_H +#define INTEL_DRM_WINSYS_H + +#include "i965/brw_winsys.h" + +#include "drm.h" +#include "intel_bufmgr.h" + + + +/* + * Winsys + */ + + +struct i965_libdrm_winsys +{ + struct brw_winsys_screen base; + drm_intel_bufmgr *gem; + + boolean send_cmd; + + int fd; /**< Drm file discriptor */ + + unsigned id; +}; + +static INLINE struct i965_libdrm_winsys * +i965_libdrm_winsys(struct brw_winsys_screen *iws) +{ + return (struct i965_libdrm_winsys *)iws; +} + +struct i965_libdrm_winsys *i965_libdrm_winsys_create(int fd, unsigned pci_id); + +void i965_libdrm_winsys_init_buffer_functions(struct i965_libdrm_winsys *idws); + + +/* Buffer. + */ +struct i965_libdrm_buffer { + struct brw_winsys_buffer base; + + drm_intel_bo *bo; + + void *ptr; + unsigned map_count; + unsigned data_type; /* valid while mapped */ + unsigned tiling; + + boolean map_gtt; + boolean flinked; + unsigned flink; +}; + +static INLINE struct i965_libdrm_buffer * +i965_libdrm_buffer(struct brw_winsys_buffer *buffer) +{ + return (struct i965_libdrm_buffer *)buffer; +} + + +#endif diff --git a/src/gallium/winsys/drm/i965/xlib/Makefile b/src/gallium/winsys/drm/i965/xlib/Makefile new file mode 100644 index 00000000000..0efa0ca6f9a --- /dev/null +++ b/src/gallium/winsys/drm/i965/xlib/Makefile @@ -0,0 +1,97 @@ +# src/gallium/winsys/xlib/Makefile + +# This makefile produces a "stand-alone" libGL.so which is based on +# Xlib (no DRI HW acceleration) + + +TOP = ../../../../../.. +include $(TOP)/configs/current + + +GL_MAJOR = 1 +GL_MINOR = 5 +GL_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY) + + +INCLUDE_DIRS = \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/main \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/drivers/i965 \ + -I$(TOP)/src/gallium/drivers/i965/include \ + -I$(TOP)/src/gallium/state_trackers/glx/xlib \ + -I$(TOP)/src/gallium/auxiliary \ + -I/usr/include/drm + +XLIB_WINSYS_SOURCES = \ + xlib_i965.c \ + + + +XLIB_WINSYS_OBJECTS = $(XLIB_WINSYS_SOURCES:.c=.o) + + + +LIBS = \ + $(TOP)/src/gallium/drivers/i965/libi965.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/state_trackers/glx/xlib/libxlib.a \ + $(TOP)/src/mesa/libglapi.a \ + $(TOP)/src/mesa/libmesagallium.a \ + $(GALLIUM_AUXILIARIES) + +# $(TOP)/src/gallium/drivers/i965/lib/libi9xx.a \ + +.SUFFIXES : .cpp + +.c.o: + $(CC) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) $< -o $@ + +.cpp.o: + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CXXFLAGS) $< -o $@ + + + +default: $(TOP)/$(LIB_DIR)/gallium $(TOP)/$(LIB_DIR)/gallium/$(GL_LIB_NAME) + +$(TOP)/$(LIB_DIR)/gallium: + @ mkdir -p $(TOP)/$(LIB_DIR)/gallium + +# Make the libGL.so library +$(TOP)/$(LIB_DIR)/gallium/$(GL_LIB_NAME): $(XLIB_WINSYS_OBJECTS) $(LIBS) Makefile + $(TOP)/bin/mklib -o $(GL_LIB) \ + -linker "$(CC)" \ + -major $(GL_MAJOR) -minor $(GL_MINOR) -patch $(GL_TINY) \ + -install $(TOP)/$(LIB_DIR)/gallium \ + $(MKLIB_OPTIONS) $(XLIB_WINSYS_OBJECTS) \ + -Wl,--start-group $(LIBS) -Wl,--end-group $(GL_LIB_DEPS) + + +depend: $(XLIB_WINSYS_SOURCES) + @ echo "running $(MKDEP)" + @ rm -f depend # workaround oops on gutsy?!? + @ touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(XLIB_WINSYS_SOURCES) \ + > /dev/null 2>/dev/null + + +install: default + $(INSTALL) -d $(INSTALL_DIR)/include/GL + $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR) + $(INSTALL) -m 644 $(TOP)/include/GL/*.h $(INSTALL_DIR)/include/GL + @if [ -e $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) ]; then \ + $(MINSTALL) $(TOP)/$(LIB_DIR)/libGL* $(INSTALL_DIR)/$(LIB_DIR); \ + fi + + +# Emacs tags +tags: + etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h + +clean: + -rm -f *.o + + +include depend diff --git a/src/gallium/winsys/drm/i965/xlib/xlib_i965.c b/src/gallium/winsys/drm/i965/xlib/xlib_i965.c new file mode 100644 index 00000000000..d2b9a1ab311 --- /dev/null +++ b/src/gallium/winsys/drm/i965/xlib/xlib_i965.c @@ -0,0 +1,522 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA + * 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: + * Keith Whitwell + * Brian Paul + */ + + +#include "util/u_memory.h" +#include "util/u_math.h" +#include "pipe/p_error.h" +#include "pipe/p_context.h" + +#include "xm_winsys.h" + +#include "i965/brw_winsys.h" +#include "i965/brw_screen.h" +#include "i965/brw_reg.h" +#include "i965/brw_structs_dump.h" + +#define MAX_VRAM (128*1024*1024) + + + +extern int brw_disasm (FILE *file, + const struct brw_instruction *inst, + unsigned count ); + +extern int intel_decode(const uint32_t *data, + int count, + uint32_t hw_offset, + uint32_t devid); + +struct xlib_brw_buffer +{ + struct brw_winsys_buffer base; + char *virtual; + unsigned offset; + unsigned type; + int map_count; + boolean modified; +}; + + +/** + * Subclass of brw_winsys_screen for Xlib winsys + */ +struct xlib_brw_winsys +{ + struct brw_winsys_screen base; + struct brw_chipset chipset; + + unsigned size; + unsigned used; +}; + +static struct xlib_brw_winsys * +xlib_brw_winsys( struct brw_winsys_screen *screen ) +{ + return (struct xlib_brw_winsys *)screen; +} + + +static struct xlib_brw_buffer * +xlib_brw_buffer( struct brw_winsys_buffer *buffer ) +{ + return (struct xlib_brw_buffer *)buffer; +} + + + +const char *names[BRW_BUFFER_TYPE_MAX] = { + "TEXTURE", + "SCANOUT", + "VERTEX", + "CURBE", + "QUERY", + "SHADER_CONSTANTS", + "WM_SCRATCH", + "BATCH", + "GENERAL_STATE", + "SURFACE_STATE", + "PIXEL", + "GENERIC", +}; + +const char *usages[BRW_USAGE_MAX] = { + "STATE", + "QUERY_RESULT", + "RENDER_TARGET", + "DEPTH_BUFFER", + "BLIT_SOURCE", + "BLIT_DEST", + "SAMPLER", + "VERTEX", + "SCRATCH" +}; + + +const char *data_types[BRW_DATA_MAX] = +{ + "GS: CC_VP", + "GS: CC_UNIT", + "GS: WM_PROG", + "GS: SAMPLER_DEFAULT_COLOR", + "GS: SAMPLER", + "GS: WM_UNIT", + "GS: SF_PROG", + "GS: SF_VP", + "GS: SF_UNIT", + "GS: VS_UNIT", + "GS: VS_PROG", + "GS: GS_UNIT", + "GS: GS_PROG", + "GS: CLIP_VP", + "GS: CLIP_UNIT", + "GS: CLIP_PROG", + "SS: SURFACE", + "SS: SURF_BIND", + "CONSTANT DATA", + "BATCH DATA", + "(untyped)" +}; + + +static enum pipe_error +xlib_brw_bo_alloc( struct brw_winsys_screen *sws, + enum brw_buffer_type type, + unsigned size, + unsigned alignment, + struct brw_winsys_buffer **bo_out ) +{ + struct xlib_brw_winsys *xbw = xlib_brw_winsys(sws); + struct xlib_brw_buffer *buf; + + if (BRW_DEBUG & DEBUG_WINSYS) + debug_printf("%s type %s sz %d align %d\n", + __FUNCTION__, names[type], size, alignment ); + + buf = CALLOC_STRUCT(xlib_brw_buffer); + if (!buf) + return PIPE_ERROR_OUT_OF_MEMORY; + + pipe_reference_init(&buf->base.reference, 1); + + buf->offset = align(xbw->used, alignment); + buf->type = type; + buf->virtual = MALLOC(size); + buf->base.size = size; + buf->base.sws = sws; + + xbw->used = align(xbw->used, alignment) + size; + if (xbw->used > MAX_VRAM) + goto err; + + /* XXX: possibly rentrant call to bo_destroy: + */ + bo_reference(bo_out, &buf->base); + return PIPE_OK; + +err: + assert(0); + FREE(buf->virtual); + FREE(buf); + return PIPE_ERROR_OUT_OF_MEMORY; +} + +static void +xlib_brw_bo_destroy( struct brw_winsys_buffer *buffer ) +{ + struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer); + + FREE(buf); +} + +static int +xlib_brw_bo_emit_reloc( struct brw_winsys_buffer *buffer, + enum brw_buffer_usage usage, + unsigned delta, + unsigned offset, + struct brw_winsys_buffer *buffer2) +{ + struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer); + struct xlib_brw_buffer *buf2 = xlib_brw_buffer(buffer2); + + if (BRW_DEBUG & DEBUG_WINSYS) + debug_printf("%s buf %p offset %x val %x + %x buf2 %p/%s/%s\n", + __FUNCTION__, (void *)buffer, offset, + buf2->offset, delta, + (void *)buffer2, names[buf2->type], usages[usage]); + + *(uint32_t *)(buf->virtual + offset) = buf2->offset + delta; + + return 0; +} + +static int +xlib_brw_bo_exec( struct brw_winsys_buffer *buffer, + unsigned bytes_used ) +{ + if (BRW_DEBUG & DEBUG_WINSYS) + debug_printf("execute buffer %p, bytes %d\n", (void *)buffer, bytes_used); + + return 0; +} + + + + +static int +xlib_brw_bo_subdata(struct brw_winsys_buffer *buffer, + enum brw_buffer_data_type data_type, + size_t offset, + size_t size, + const void *data, + const struct brw_winsys_reloc *reloc, + unsigned nr_relocs) +{ + struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer); + struct xlib_brw_winsys *xbw = xlib_brw_winsys(buffer->sws); + unsigned i; + + if (BRW_DEBUG & DEBUG_WINSYS) + debug_printf("%s buf %p off %d sz %d %s relocs: %d\n", + __FUNCTION__, + (void *)buffer, offset, size, + data_types[data_type], + nr_relocs); + + assert(buf->base.size >= offset + size); + memcpy(buf->virtual + offset, data, size); + + /* Apply the relocations: + */ + for (i = 0; i < nr_relocs; i++) { + if (BRW_DEBUG & DEBUG_WINSYS) + debug_printf("\treloc[%d] usage %s off %d value %x+%x\n", + i, usages[reloc[i].usage], reloc[i].offset, + xlib_brw_buffer(reloc[i].bo)->offset, reloc[i].delta); + + *(unsigned *)(buf->virtual + offset + reloc[i].offset) = + xlib_brw_buffer(reloc[i].bo)->offset + reloc[i].delta; + } + + if (BRW_DUMP) + brw_dump_data( xbw->chipset.pci_id, + data_type, + buf->offset + offset, + buf->virtual + offset, size ); + + + return 0; +} + + +static boolean +xlib_brw_bo_is_busy(struct brw_winsys_buffer *buffer) +{ + if (BRW_DEBUG & DEBUG_WINSYS) + debug_printf("%s %p\n", __FUNCTION__, (void *)buffer); + return TRUE; +} + +static boolean +xlib_brw_bo_references(struct brw_winsys_buffer *a, + struct brw_winsys_buffer *b) +{ + if (BRW_DEBUG & DEBUG_WINSYS) + debug_printf("%s %p %p\n", __FUNCTION__, (void *)a, (void *)b); + return TRUE; +} + +static enum pipe_error +xlib_brw_check_aperture_space( struct brw_winsys_screen *iws, + struct brw_winsys_buffer **buffers, + unsigned count ) +{ + unsigned tot_size = 0; + unsigned i; + + for (i = 0; i < count; i++) + tot_size += buffers[i]->size; + + if (BRW_DEBUG & DEBUG_WINSYS) + debug_printf("%s %d bufs, tot_size: %d kb\n", + __FUNCTION__, count, + (tot_size + 1023) / 1024); + + return PIPE_OK; +} + +static void * +xlib_brw_bo_map(struct brw_winsys_buffer *buffer, + enum brw_buffer_data_type data_type, + unsigned offset, + unsigned length, + boolean write, + boolean discard, + boolean explicit) +{ + struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer); + + if (BRW_DEBUG & DEBUG_WINSYS) + debug_printf("%s %p %s %s\n", __FUNCTION__, (void *)buffer, + write ? "read/write" : "read", + write ? data_types[data_type] : ""); + + if (write) + buf->modified = 1; + + buf->map_count++; + return buf->virtual; +} + + +static void +xlib_brw_bo_flush_range( struct brw_winsys_buffer *buffer, + unsigned offset, + unsigned length ) +{ +} + + +static void +xlib_brw_bo_unmap(struct brw_winsys_buffer *buffer) +{ + struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer); + + if (BRW_DEBUG & DEBUG_WINSYS) + debug_printf("%s %p\n", __FUNCTION__, (void *)buffer); + + --buf->map_count; + assert(buf->map_count >= 0); + + if (buf->map_count == 0 && + buf->modified) { + + buf->modified = 0; + + /* Consider dumping new buffer contents here, using the + * flush-range info to minimize verbosity. + */ + } +} + + +static void +xlib_brw_bo_wait_idle( struct brw_winsys_buffer *buffer ) +{ +} + + +static void +xlib_brw_winsys_destroy( struct brw_winsys_screen *sws ) +{ + struct xlib_brw_winsys *xbw = xlib_brw_winsys(sws); + + FREE(xbw); +} + +static struct brw_winsys_screen * +xlib_create_brw_winsys_screen( void ) +{ + struct xlib_brw_winsys *ws; + + ws = CALLOC_STRUCT(xlib_brw_winsys); + if (!ws) + return NULL; + + ws->used = 0; + + ws->base.destroy = xlib_brw_winsys_destroy; + ws->base.bo_alloc = xlib_brw_bo_alloc; + ws->base.bo_destroy = xlib_brw_bo_destroy; + ws->base.bo_emit_reloc = xlib_brw_bo_emit_reloc; + ws->base.bo_exec = xlib_brw_bo_exec; + ws->base.bo_subdata = xlib_brw_bo_subdata; + ws->base.bo_is_busy = xlib_brw_bo_is_busy; + ws->base.bo_references = xlib_brw_bo_references; + ws->base.check_aperture_space = xlib_brw_check_aperture_space; + ws->base.bo_map = xlib_brw_bo_map; + ws->base.bo_flush_range = xlib_brw_bo_flush_range; + ws->base.bo_unmap = xlib_brw_bo_unmap; + ws->base.bo_wait_idle = xlib_brw_bo_wait_idle; + + return &ws->base; +} + + +/*********************************************************************** + * Implementation of Xlib co-state-tracker's winsys interface + */ + +static void +xlib_i965_display_surface(struct xmesa_buffer *xm_buffer, + struct pipe_surface *surf) +{ + struct brw_surface *surface = brw_surface(surf); + struct xlib_brw_buffer *bo = xlib_brw_buffer(surface->bo); + + if (BRW_DEBUG & DEBUG_WINSYS) + debug_printf("%s offset %x+%x sz %dx%d\n", __FUNCTION__, + bo->offset, + surface->draw_offset, + surf->width, + surf->height); +} + +static void +xlib_i965_flush_frontbuffer(struct pipe_screen *screen, + struct pipe_surface *surf, + void *context_private) +{ + xlib_i965_display_surface(NULL, surf); +} + + +static struct pipe_screen * +xlib_create_i965_screen( void ) +{ + struct brw_winsys_screen *winsys; + struct pipe_screen *screen; + + winsys = xlib_create_brw_winsys_screen(); + if (winsys == NULL) + return NULL; + + screen = brw_create_screen(winsys, PCI_CHIP_GM45_GM); + if (screen == NULL) + goto fail; + + xlib_brw_winsys(winsys)->chipset = brw_screen(screen)->chipset; + + screen->flush_frontbuffer = xlib_i965_flush_frontbuffer; + return screen; + +fail: + if (winsys) + winsys->destroy( winsys ); + + return NULL; +} + + +static struct pipe_context * +xlib_create_i965_context( struct pipe_screen *screen, + void *context_private ) +{ + struct pipe_context *pipe; + + pipe = brw_create_context(screen); + if (pipe == NULL) + goto fail; + + pipe->priv = context_private; + return pipe; + +fail: + /* Free stuff here */ + return NULL; +} + + + + +struct xm_driver xlib_i965_driver = +{ + .create_pipe_screen = xlib_create_i965_screen, + .create_pipe_context = xlib_create_i965_context, + .display_surface = xlib_i965_display_surface +}; + + +/* Register this driver at library load: + */ +static void _init( void ) __attribute__((constructor)); +static void _init( void ) +{ + xmesa_set_driver( &xlib_i965_driver ); +} + + + +/*********************************************************************** + * + * Butt-ugly hack to convince the linker not to throw away public GL + * symbols (they are all referenced from getprocaddress, I guess). + */ +extern void (*linker_foo(const unsigned char *procName))(); +extern void (*glXGetProcAddress(const unsigned char *procName))(); + +extern void (*linker_foo(const unsigned char *procName))() +{ + return glXGetProcAddress(procName); +} diff --git a/src/gallium/winsys/drm/i965/xorg/Makefile b/src/gallium/winsys/drm/i965/xorg/Makefile new file mode 100644 index 00000000000..d91d0006efd --- /dev/null +++ b/src/gallium/winsys/drm/i965/xorg/Makefile @@ -0,0 +1,57 @@ +TARGET = modesetting_drv.so +CFILES = $(wildcard ./*.c) +OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES)) +TOP = ../../../../../.. + +include $(TOP)/configs/current + +INCLUDES = \ + $(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \ + -I../gem \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/mesa \ + -I$(TOP)/include \ + -I$(TOP)/src/egl/main + +LIBS = \ + $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \ + $(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \ + $(TOP)/src/gallium/drivers/i965/libi965.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(GALLIUM_AUXILIARIES) + +DRIVER_DEFINES = \ + -DHAVE_CONFIG_H + + +############################################# + + + +all default: $(TARGET) + +$(TARGET): $(OBJECTS) Makefile $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a $(LIBS) + $(TOP)/bin/mklib -noprefix -o $@ \ + $(OBJECTS) $(LIBS) $(shell pkg-config --libs libdrm) -ldrm_intel + +clean: + rm -rf $(OBJECTS) $(TARGET) + +install: + $(INSTALL) -d $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) + $(MINSTALL) -m 755 $(TARGET) $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) + + +############################################## + + +.c.o: + $(CC) -c $(CFLAGS) $(INCLUDES) $(DRIVER_DEFINES) $< -o $@ + + +############################################## + +.PHONY = all clean install diff --git a/src/gallium/winsys/drm/i965/xorg/intel_xorg.c b/src/gallium/winsys/drm/i965/xorg/intel_xorg.c new file mode 100644 index 00000000000..ac691cb76b3 --- /dev/null +++ b/src/gallium/winsys/drm/i965/xorg/intel_xorg.c @@ -0,0 +1,147 @@ +/* + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 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 TUNGSTEN GRAPHICS 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. + * + * + * Author: Alan Hourihane <[email protected]> + * Author: Jakob Bornecrantz <[email protected]> + * + */ + +#include "../../../../state_trackers/xorg/xorg_winsys.h" + +static void intel_xorg_identify(int flags); +static Bool intel_xorg_pci_probe(DriverPtr driver, + int entity_num, + struct pci_device *device, + intptr_t match_data); + +static const struct pci_id_match intel_xorg_device_match[] = { + {0x8086, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0}, + {0, 0, 0}, +}; + +static SymTabRec intel_xorg_chipsets[] = { + {PCI_MATCH_ANY, "Intel Graphics Device"}, + {-1, NULL} +}; + +static PciChipsets intel_xorg_pci_devices[] = { + {PCI_MATCH_ANY, PCI_MATCH_ANY, NULL}, + {-1, -1, NULL} +}; + +static XF86ModuleVersionInfo intel_xorg_version = { + "modesetting", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 0, 1, 0, /* major, minor, patch */ + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0, 0, 0, 0} +}; + +/* + * Xorg driver exported structures + */ + +_X_EXPORT DriverRec modesetting = { + 1, + "modesetting", + intel_xorg_identify, + NULL, + xorg_tracker_available_options, + NULL, + 0, + NULL, + intel_xorg_device_match, + intel_xorg_pci_probe +}; + +static MODULESETUPPROTO(intel_xorg_setup); + +_X_EXPORT XF86ModuleData modesettingModuleData = { + &intel_xorg_version, + intel_xorg_setup, + NULL +}; + +/* + * Xorg driver functions + */ + +static pointer +intel_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = 0; + + /* This module should be loaded only once, but check to be sure. + */ + if (!setupDone) { + setupDone = 1; + xf86AddDriver(&modesetting, module, HaveDriverFuncs); + + /* + * The return value must be non-NULL on success even though there + * is no TearDownProc. + */ + return (pointer) 1; + } else { + if (errmaj) + *errmaj = LDR_ONCEONLY; + return NULL; + } +} + +static void +intel_xorg_identify(int flags) +{ + xf86PrintChipsets("modesetting", "Driver for Modesetting Kernel Drivers", + intel_xorg_chipsets); +} + +static Bool +intel_xorg_pci_probe(DriverPtr driver, + int entity_num, struct pci_device *device, intptr_t match_data) +{ + ScrnInfoPtr scrn = NULL; + EntityInfoPtr entity; + + scrn = xf86ConfigPciEntity(scrn, 0, entity_num, intel_xorg_pci_devices, + NULL, NULL, NULL, NULL, NULL); + if (scrn != NULL) { + scrn->driverVersion = 1; + scrn->driverName = "i965"; + scrn->name = "modesetting"; + scrn->Probe = NULL; + + entity = xf86GetEntityInfo(entity_num); + + /* Use all the functions from the xorg tracker */ + xorg_tracker_set_functions(scrn); + } + return scrn != NULL; +} diff --git a/src/gallium/winsys/drm/intel/dri/Makefile b/src/gallium/winsys/drm/intel/dri/Makefile index c0ecd9680e2..26aae4122eb 100644 --- a/src/gallium/winsys/drm/intel/dri/Makefile +++ b/src/gallium/winsys/drm/intel/dri/Makefile @@ -24,4 +24,3 @@ DRI_LIB_DEPS += -ldrm_intel symlinks: $(TOP)/$(LIB_DIR)/gallium @rm -f $(TOP)/$(LIB_DIR)/gallium/i965_dri.so - ln -s i915_dri.so $(TOP)/$(LIB_DIR)/gallium/i965_dri.so diff --git a/src/gallium/winsys/drm/intel/dri/SConscript b/src/gallium/winsys/drm/intel/dri/SConscript index b1b654d9f8b..104e987083f 100644 --- a/src/gallium/winsys/drm/intel/dri/SConscript +++ b/src/gallium/winsys/drm/intel/dri/SConscript @@ -15,6 +15,6 @@ drivers = [ env.LoadableModule( target ='i915_dri.so', source = COMMON_GALLIUM_SOURCES, - LIBS = drivers + mesa + auxiliaries + env['LIBS'], + LIBS = drivers + mesa + gallium + env['LIBS'], SHLIBPREFIX = '', ) diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_api.c b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c index 9ed570ff6e4..5ed2a10af1c 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_drm_api.c +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c @@ -32,6 +32,7 @@ intel_drm_get_device_id(unsigned int *device_id) } shutup_gcc = fgets(path, sizeof(path), file); + (void) shutup_gcc; sscanf(path, "%x", device_id); fclose(file); } diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c b/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c index e70bfe7b44e..e8b58742ab7 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c @@ -39,11 +39,12 @@ intel_drm_fence_reference(struct intel_winsys *iws, struct intel_drm_fence *old = (struct intel_drm_fence *)*ptr; struct intel_drm_fence *f = (struct intel_drm_fence *)fence; - if (pipe_reference((struct pipe_reference**)ptr, &f->reference)) { + if (pipe_reference(&((struct intel_drm_fence *)(*ptr))->reference, &f->reference)) { if (old->bo) drm_intel_bo_unreference(old->bo); FREE(old); } + *ptr = fence; } static int diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c index f512c0e5f32..7106a06492d 100644 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c @@ -1,5 +1,6 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "util/u_format.h" #include "util/u_memory.h" #include "nouveau_drm_api.h" @@ -21,15 +22,13 @@ dri_surface_from_handle(struct drm_api *api, struct pipe_screen *pscreen, struct pipe_texture tmpl; memset(&tmpl, 0, sizeof(tmpl)); - tmpl.tex_usage = PIPE_TEXTURE_USAGE_PRIMARY | - NOUVEAU_TEXTURE_USAGE_LINEAR; + tmpl.tex_usage = PIPE_TEXTURE_USAGE_PRIMARY; tmpl.target = PIPE_TEXTURE_2D; tmpl.last_level = 0; - tmpl.depth[0] = 1; + tmpl.depth0 = 1; tmpl.format = format; - tmpl.width[0] = width; - tmpl.height[0] = height; - pf_get_block(tmpl.format, &tmpl.block); + tmpl.width0 = width; + tmpl.height0 = height; pt = api->texture_from_shared_handle(api, pscreen, &tmpl, "front buffer", pitch, handle); @@ -248,7 +247,7 @@ nouveau_drm_handle_from_pt(struct drm_api *api, struct pipe_screen *pscreen, return false; *handle = mt->bo->handle; - *stride = mt->base.nblocksx[0] * mt->base.block.size; + *stride = util_format_get_stride(mt->base.format, mt->base.width0); return true; } diff --git a/src/gallium/winsys/drm/radeon/core/Makefile b/src/gallium/winsys/drm/radeon/core/Makefile index 42a6f4abc21..860cbb6dbf8 100644 --- a/src/gallium/winsys/drm/radeon/core/Makefile +++ b/src/gallium/winsys/drm/radeon/core/Makefile @@ -7,8 +7,7 @@ LIBNAME = radeonwinsys C_SOURCES = \ radeon_buffer.c \ radeon_drm.c \ - radeon_r300.c \ - radeon_winsys_softpipe.c + radeon_r300.c LIBRARY_INCLUDES = -I$(TOP)/src/gallium/drivers/r300 \ $(shell pkg-config libdrm --cflags-only-I) diff --git a/src/gallium/winsys/drm/radeon/core/SConscript b/src/gallium/winsys/drm/radeon/core/SConscript index 2ad68e403fe..f4e9c397bdf 100644 --- a/src/gallium/winsys/drm/radeon/core/SConscript +++ b/src/gallium/winsys/drm/radeon/core/SConscript @@ -6,7 +6,6 @@ radeon_sources = [ 'radeon_buffer.c', 'radeon_drm.c', 'radeon_r300.c', - 'radeon_winsys_softpipe.c', ] env.Append(CPPPATH = '#/src/gallium/drivers/r300') diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c index 7bf23cba236..d2367b245a2 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c @@ -33,6 +33,18 @@ #include "radeon_buffer.h" #include "radeon_bo_gem.h" +#include "softpipe/sp_texture.h" +#include "r300_context.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include <X11/Xutil.h> + +struct radeon_vl_context +{ + Display *display; + int screen; + Drawable drawable; +}; static const char *radeon_get_name(struct pipe_winsys *ws) { @@ -104,17 +116,13 @@ static struct pipe_buffer *radeon_surface_buffer_create(struct pipe_winsys *ws, unsigned tex_usage, unsigned *stride) { - struct pipe_format_block block; - unsigned nblocksx, nblocksy, size; - - pf_get_block(format, &block); - - nblocksx = pf_get_nblocksx(&block, width); - nblocksy = pf_get_nblocksy(&block, height); - /* Radeons enjoy things in multiples of 32. */ /* XXX this can be 32 when POT */ - *stride = (nblocksx * block.size + 63) & ~63; + const unsigned alignment = 64; + unsigned nblocksy, size; + + nblocksy = util_format_get_nblocksy(format, height); + *stride = align(util_format_get_stride(format, width), alignment); size = *stride * nblocksy; return radeon_buffer_create(ws, 64, usage, size); @@ -133,10 +141,15 @@ static void *radeon_buffer_map(struct pipe_winsys *ws, struct pipe_buffer *buffer, unsigned flags) { + struct radeon_winsys_priv *priv = ((struct radeon_winsys *)ws)->priv; struct radeon_pipe_buffer *radeon_buffer = (struct radeon_pipe_buffer*)buffer; int write = 0; + if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) { + priv->flush_cb(priv->flush_data); + } + if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { uint32_t domain; @@ -183,11 +196,53 @@ static int radeon_fence_finish(struct pipe_winsys *ws, return 0; } +static void radeon_display_surface(struct pipe_winsys *pws, + struct pipe_surface *psurf, + struct radeon_vl_context *rvl_ctx) +{ + struct r300_texture *r300tex = (struct r300_texture *)(psurf->texture); + XImage *ximage; + void *data; + + ximage = XCreateImage(rvl_ctx->display, + XDefaultVisual(rvl_ctx->display, rvl_ctx->screen), + XDefaultDepth(rvl_ctx->display, rvl_ctx->screen), + ZPixmap, 0, /* format, offset */ + NULL, /* data */ + 0, 0, /* size */ + 32, /* bitmap_pad */ + 0); /* bytes_per_line */ + + assert(ximage->format); + assert(ximage->bitmap_unit); + + data = pws->buffer_map(pws, r300tex->buffer, 0); + + /* update XImage's fields */ + ximage->data = data; + ximage->width = psurf->width; + ximage->height = psurf->height; + ximage->bytes_per_line = psurf->width * (ximage->bits_per_pixel >> 3); + + XPutImage(rvl_ctx->display, rvl_ctx->drawable, + XDefaultGC(rvl_ctx->display, rvl_ctx->screen), + ximage, 0, 0, 0, 0, psurf->width, psurf->height); + + XSync(rvl_ctx->display, 0); + + ximage->data = NULL; + XDestroyImage(ximage); + + pws->buffer_unmap(pws, r300tex->buffer); +} + static void radeon_flush_frontbuffer(struct pipe_winsys *pipe_winsys, struct pipe_surface *pipe_surface, void *context_private) { - /* XXX TODO: call dri2CopyRegion */ + struct radeon_vl_context *rvl_ctx; + rvl_ctx = (struct radeon_vl_context *) context_private; + radeon_display_surface(pipe_winsys, pipe_surface, rvl_ctx); } struct radeon_winsys* radeon_pipe_winsys(int fd) @@ -266,13 +321,10 @@ struct pipe_surface *radeon_surface_from_handle(struct radeon_context *radeon_co memset(&tmpl, 0, sizeof(tmpl)); tmpl.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET; tmpl.target = PIPE_TEXTURE_2D; - tmpl.width[0] = w; - tmpl.height[0] = h; - tmpl.depth[0] = 1; + tmpl.width0 = w; + tmpl.height0 = h; + tmpl.depth0 = 1; tmpl.format = format; - pf_get_block(tmpl.format, &tmpl.block); - tmpl.nblocksx[0] = pf_get_nblocksx(&tmpl.block, w); - tmpl.nblocksy[0] = pf_get_nblocksy(&tmpl.block, h); pt = pipe_screen->texture_blanket(pipe_screen, &tmpl, &pitch, pb); if (pt == NULL) { diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h index f5153b06af5..d7f17564a9f 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h @@ -45,6 +45,8 @@ #include "radeon_drm.h" +#include "radeon_winsys.h" + struct radeon_pipe_buffer { struct pipe_buffer base; struct radeon_bo *bo; @@ -66,14 +68,10 @@ struct radeon_winsys_priv { /* Current CS. */ struct radeon_cs* cs; -}; - -struct radeon_winsys { - /* Parent class. */ - struct pipe_winsys base; - /* This corresponds to void* radeon_winsys in r300_winsys. */ - struct radeon_winsys_priv* priv; + /* Flush CB */ + void (*flush_cb)(void *); + void *flush_data; }; struct radeon_winsys* radeon_pipe_winsys(int fb); diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.c b/src/gallium/winsys/drm/radeon/core/radeon_drm.c index caab33de1cc..05194fc52a2 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.c @@ -29,21 +29,95 @@ * Joakim Sindholt <[email protected]> */ +#include "softpipe/sp_winsys.h" + #include "radeon_drm.h" +/* Helper function to do the ioctls needed for setup and init. */ +static void do_ioctls(int fd, struct radeon_winsys* winsys) +{ + struct drm_radeon_gem_info gem_info = {0}; + struct drm_radeon_info info = {0}; + int target = 0; + int retval; + + info.value = (unsigned long)⌖ + + /* We do things in a specific order here. + * + * First, the PCI ID. This is essential and should return usable numbers + * for all Radeons. If this fails, we probably got handed an FD for some + * non-Radeon card. + * + * The GB and Z pipe requests should always succeed, but they might not + * return sensical values for all chipsets, but that's alright because + * the pipe drivers already know that. + * + * The GEM info is actually bogus on the kernel side, as well as our side + * (see radeon_gem_info_ioctl in radeon_gem.c) but that's alright because + * we don't actually use the info for anything yet. + * XXX update the above when we can safely use vram_size instead of vram_visible */ + info.request = RADEON_INFO_DEVICE_ID; + retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); + if (retval) { + fprintf(stderr, "%s: Failed to get PCI ID, " + "error number %d\n", __FUNCTION__, retval); + exit(1); + } + winsys->pci_id = target; + + info.request = RADEON_INFO_NUM_GB_PIPES; + retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); + if (retval) { + fprintf(stderr, "%s: Failed to get GB pipe count, " + "error number %d\n", __FUNCTION__, retval); + exit(1); + } + winsys->gb_pipes = target; + + info.request = RADEON_INFO_NUM_Z_PIPES; + retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); + if (retval) { + fprintf(stderr, "%s: Failed to get Z pipe count, " + "error number %d\n", __FUNCTION__, retval); + exit(1); + } + winsys->z_pipes = target; + + retval = drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO, + &gem_info, sizeof(gem_info)); + if (retval) { + fprintf(stderr, "%s: Failed to get MM info, error number %d\n", + __FUNCTION__, retval); + exit(1); + } + winsys->gart_size = gem_info.gart_size; + /* XXX */ + winsys->vram_size = gem_info.vram_visible; +} + +/* Guess at whether this chipset should use r300g. + * + * I believe that this check is valid, but I haven't been exhaustive. */ +static boolean is_r3xx(int pciid) +{ + return (pciid > 0x3150) && (pciid < 0x796f); +} + /* Create a pipe_screen. */ struct pipe_screen* radeon_create_screen(struct drm_api* api, int drmFB, struct drm_create_screen_arg *arg) { - struct radeon_winsys* winsys = radeon_pipe_winsys(drmFB); + struct radeon_winsys* rwinsys = radeon_pipe_winsys(drmFB); + do_ioctls(drmFB, rwinsys); - if (getenv("RADEON_SOFTPIPE")) { - return softpipe_create_screen((struct pipe_winsys*)winsys); + if (!is_r3xx(rwinsys->pci_id) || + debug_get_bool_option("RADEON_SOFTPIPE", FALSE)) { + return softpipe_create_screen((struct pipe_winsys*)rwinsys); } else { - struct r300_winsys* r300 = radeon_create_r300_winsys(drmFB, winsys); - FREE(winsys); - return r300_create_screen(r300); + radeon_setup_winsys(drmFB, rwinsys); + return r300_create_screen(rwinsys); } } @@ -51,11 +125,13 @@ struct pipe_screen* radeon_create_screen(struct drm_api* api, struct pipe_context* radeon_create_context(struct drm_api* api, struct pipe_screen* screen) { - if (getenv("RADEON_SOFTPIPE")) { - return radeon_create_softpipe(screen->winsys); + struct radeon_winsys* rwinsys = (struct radeon_winsys*)screen->winsys; + + if (!is_r3xx(rwinsys->pci_id) || + debug_get_bool_option("RADEON_SOFTPIPE", FALSE)) { + return softpipe_create(screen); } else { - return r300_create_context(screen, - (struct r300_winsys*)screen->winsys); + return r300_create_context(screen, rwinsys); } } @@ -130,7 +206,7 @@ static boolean radeon_shared_handle_from_texture(struct drm_api *api, int retval, fd; struct drm_gem_flink flink; struct radeon_pipe_buffer* radeon_buffer; - struct pipe_buffer *buffer; + struct pipe_buffer *buffer = NULL; if (!radeon_buffer_from_texture(api, texture, &buffer, stride)) { return FALSE; @@ -163,7 +239,7 @@ static boolean radeon_local_handle_from_texture(struct drm_api *api, unsigned *stride, unsigned *handle) { - struct pipe_buffer *buffer; + struct pipe_buffer *buffer = NULL; if (!radeon_buffer_from_texture(api, texture, &buffer, stride)) { return FALSE; } diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.h b/src/gallium/winsys/drm/radeon/core/radeon_drm.h index 88a5c82b284..bf0e78138d7 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.h @@ -37,13 +37,13 @@ #include "pipe/p_screen.h" #include "trace/tr_drm.h" +#include "util/u_debug.h" #include "util/u_memory.h" #include "state_tracker/drm_api.h" #include "radeon_buffer.h" #include "radeon_r300.h" -#include "radeon_winsys_softpipe.h" /* XXX */ #include "r300_screen.h" diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.c b/src/gallium/winsys/drm/radeon/core/radeon_r300.c index d2d84f1a8f0..0875ee41cbf 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.c @@ -22,25 +22,29 @@ #include "radeon_r300.h" -static boolean radeon_r300_add_buffer(struct r300_winsys* winsys, - struct pipe_buffer* pbuffer, - uint32_t rd, - uint32_t wd) +static void radeon_set_flush_cb(struct radeon_winsys *winsys, + void (*flush_cb)(void *), + void *data) +{ + winsys->priv->flush_cb = flush_cb; + winsys->priv->flush_data = data; + radeon_cs_space_set_flush(winsys->priv->cs, flush_cb, data); +} + +static boolean radeon_add_buffer(struct radeon_winsys* winsys, + struct pipe_buffer* pbuffer, + uint32_t rd, + uint32_t wd) { - struct radeon_winsys_priv* priv = - (struct radeon_winsys_priv*)winsys->radeon_winsys; struct radeon_bo* bo = ((struct radeon_pipe_buffer*)pbuffer)->bo; - radeon_cs_space_add_persistent_bo(priv->cs, bo, rd, wd); + radeon_cs_space_add_persistent_bo(winsys->priv->cs, bo, rd, wd); return TRUE; } -static boolean radeon_r300_validate(struct r300_winsys* winsys) +static boolean radeon_validate(struct radeon_winsys* winsys) { - struct radeon_winsys_priv* priv = - (struct radeon_winsys_priv*)winsys->radeon_winsys; - - if (radeon_cs_space_check(priv->cs) < 0) { + if (radeon_cs_space_check(winsys->priv->cs) < 0) { return FALSE; } @@ -48,45 +52,37 @@ static boolean radeon_r300_validate(struct r300_winsys* winsys) return TRUE; } -static boolean radeon_r300_check_cs(struct r300_winsys* winsys, int size) +static boolean radeon_check_cs(struct radeon_winsys* winsys, int size) { - /* XXX check size here, lazy ass! */ - /* XXX also validate buffers */ - return TRUE; + struct radeon_cs* cs = winsys->priv->cs; + + return radeon_validate(winsys) && cs->cdw + size <= cs->ndw; } -static void radeon_r300_begin_cs(struct r300_winsys* winsys, - int size, - const char* file, - const char* function, - int line) +static void radeon_begin_cs(struct radeon_winsys* winsys, + int size, + const char* file, + const char* function, + int line) { - struct radeon_winsys_priv* priv = - (struct radeon_winsys_priv*)winsys->radeon_winsys; - - radeon_cs_begin(priv->cs, size, file, function, line); + radeon_cs_begin(winsys->priv->cs, size, file, function, line); } -static void radeon_r300_write_cs_dword(struct r300_winsys* winsys, - uint32_t dword) +static void radeon_write_cs_dword(struct radeon_winsys* winsys, + uint32_t dword) { - struct radeon_winsys_priv* priv = - (struct radeon_winsys_priv*)winsys->radeon_winsys; - - radeon_cs_write_dword(priv->cs, dword); + radeon_cs_write_dword(winsys->priv->cs, dword); } -static void radeon_r300_write_cs_reloc(struct r300_winsys* winsys, - struct pipe_buffer* pbuffer, - uint32_t rd, - uint32_t wd, - uint32_t flags) +static void radeon_write_cs_reloc(struct radeon_winsys* winsys, + struct pipe_buffer* pbuffer, + uint32_t rd, + uint32_t wd, + uint32_t flags) { - struct radeon_winsys_priv* priv = - (struct radeon_winsys_priv*)winsys->radeon_winsys; int retval = 0; - retval = radeon_cs_write_reloc(priv->cs, + retval = radeon_cs_write_reloc(winsys->priv->cs, ((struct radeon_pipe_buffer*)pbuffer)->bo, rd, wd, flags); if (retval) { @@ -95,116 +91,60 @@ static void radeon_r300_write_cs_reloc(struct r300_winsys* winsys, } } -static void radeon_r300_end_cs(struct r300_winsys* winsys, - const char* file, - const char* function, - int line) +static void radeon_reset_bos(struct radeon_winsys *winsys) { - struct radeon_winsys_priv* priv = - (struct radeon_winsys_priv*)winsys->radeon_winsys; + radeon_cs_space_reset_bos(winsys->priv->cs); +} - radeon_cs_end(priv->cs, file, function, line); +static void radeon_end_cs(struct radeon_winsys* winsys, + const char* file, + const char* function, + int line) +{ + radeon_cs_end(winsys->priv->cs, file, function, line); } -static void radeon_r300_flush_cs(struct r300_winsys* winsys) +static void radeon_flush_cs(struct radeon_winsys* winsys) { - struct radeon_winsys_priv* priv = - (struct radeon_winsys_priv*)winsys->radeon_winsys; int retval; /* Emit the CS. */ - retval = radeon_cs_emit(priv->cs); + retval = radeon_cs_emit(winsys->priv->cs); if (retval) { debug_printf("radeon: Bad CS, dumping...\n"); - radeon_cs_print(priv->cs, stderr); + radeon_cs_print(winsys->priv->cs, stderr); } - /* Clean out BOs. */ - radeon_cs_space_reset_bos(priv->cs); - /* 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(priv->cs); -} - -/* Helper function to do the ioctls needed for setup and init. */ -static void do_ioctls(struct r300_winsys* winsys, int fd) -{ - struct drm_radeon_gem_info gem_info = {0}; - struct drm_radeon_info info = {0}; - int target = 0; - int retval; - - info.value = (unsigned long)⌖ - - /* First, get the number of pixel pipes */ - info.request = RADEON_INFO_NUM_GB_PIPES; - retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); - if (retval) { - fprintf(stderr, "%s: Failed to get GB pipe count, " - "error number %d\n", __FUNCTION__, retval); - exit(1); - } - winsys->gb_pipes = target; - - /* Then, get PCI ID */ - info.request = RADEON_INFO_DEVICE_ID; - retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); - if (retval) { - fprintf(stderr, "%s: Failed to get PCI ID, " - "error number %d\n", __FUNCTION__, retval); - exit(1); - } - winsys->pci_id = target; - - /* Finally, retrieve MM info */ - retval = drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO, - &gem_info, sizeof(gem_info)); - if (retval) { - fprintf(stderr, "%s: Failed to get MM info, error number %d\n", - __FUNCTION__, retval); - exit(1); - } - winsys->gart_size = gem_info.gart_size; - /* XXX */ - winsys->vram_size = gem_info.vram_visible; + radeon_cs_erase(winsys->priv->cs); } -struct r300_winsys* -radeon_create_r300_winsys(int fd, struct radeon_winsys* old_winsys) +void +radeon_setup_winsys(int fd, struct radeon_winsys* winsys) { - struct r300_winsys* winsys = CALLOC_STRUCT(r300_winsys); - struct radeon_winsys_priv* priv; - - if (winsys == NULL) { - return NULL; - } - - priv = old_winsys->priv; - - do_ioctls(winsys, fd); + struct radeon_winsys_priv* priv = winsys->priv; priv->csm = radeon_cs_manager_gem_ctor(fd); + /* Size limit on IBs is 64 kibibytes. */ priv->cs = radeon_cs_create(priv->csm, 1024 * 64 / 4); radeon_cs_set_limit(priv->cs, RADEON_GEM_DOMAIN_GTT, winsys->gart_size); radeon_cs_set_limit(priv->cs, RADEON_GEM_DOMAIN_VRAM, winsys->vram_size); - winsys->add_buffer = radeon_r300_add_buffer; - winsys->validate = radeon_r300_validate; - - winsys->check_cs = radeon_r300_check_cs; - winsys->begin_cs = radeon_r300_begin_cs; - winsys->write_cs_dword = radeon_r300_write_cs_dword; - winsys->write_cs_reloc = radeon_r300_write_cs_reloc; - winsys->end_cs = radeon_r300_end_cs; - winsys->flush_cs = radeon_r300_flush_cs; - - memcpy(winsys, old_winsys, sizeof(struct radeon_winsys)); - - return winsys; + winsys->add_buffer = radeon_add_buffer; + winsys->validate = radeon_validate; + + winsys->check_cs = radeon_check_cs; + winsys->begin_cs = radeon_begin_cs; + winsys->write_cs_dword = radeon_write_cs_dword; + winsys->write_cs_reloc = radeon_write_cs_reloc; + winsys->end_cs = radeon_end_cs; + winsys->flush_cs = radeon_flush_cs; + winsys->reset_bos = radeon_reset_bos; + winsys->set_flush_cb = radeon_set_flush_cb; } diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.h b/src/gallium/winsys/drm/radeon/core/radeon_r300.h index 775d7937fd8..cfbdb302661 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.h @@ -34,9 +34,6 @@ #include "radeon_buffer.h" -struct radeon_winsys; - -struct r300_winsys* -radeon_create_r300_winsys(int fd, struct radeon_winsys* old_winsys); +void radeon_setup_winsys(int fd, struct radeon_winsys* winsys); #endif /* RADEON_R300_H */ diff --git a/src/gallium/winsys/drm/radeon/core/radeon_winsys.h b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h new file mode 100644 index 00000000000..9edc9e038c3 --- /dev/null +++ b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h @@ -0,0 +1,105 @@ +/* + * Copyright © 2009 Corbin Simpson + * 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: + * Corbin Simpson <[email protected]> + */ +#ifndef RADEON_WINSYS_H +#define RADEON_WINSYS_H + +#include "pipe/internal/p_winsys_screen.h" + +struct radeon_winsys_priv; + +struct radeon_winsys { + /* Parent class. */ + struct pipe_winsys base; + + /* Winsys private */ + struct radeon_winsys_priv* priv; + + /* PCI ID */ + uint32_t pci_id; + + /* GB pipe count */ + uint32_t gb_pipes; + + /* Z pipe count (rv530 only) */ + uint32_t z_pipes; + + /* GART size. */ + uint32_t gart_size; + + /* VRAM size. */ + uint32_t vram_size; + + /* Add a pipe_buffer to the list of buffer objects to validate. */ + boolean (*add_buffer)(struct radeon_winsys* winsys, + struct pipe_buffer* pbuffer, + uint32_t rd, + uint32_t wd); + + /* Revalidate all currently setup pipe_buffers. + * Returns TRUE if a flush is required. */ + boolean (*validate)(struct radeon_winsys* winsys); + + /* Check to see if there's room for commands. */ + boolean (*check_cs)(struct radeon_winsys* winsys, int size); + + /* Start a command emit. */ + void (*begin_cs)(struct radeon_winsys* winsys, + int size, + const char* file, + const char* function, + int line); + + /* Write a dword to the command buffer. */ + void (*write_cs_dword)(struct radeon_winsys* winsys, uint32_t dword); + + /* Write a relocated dword to the command buffer. */ + void (*write_cs_reloc)(struct radeon_winsys* winsys, + struct pipe_buffer* bo, + uint32_t rd, + uint32_t wd, + uint32_t flags); + + /* Finish a command emit. */ + void (*end_cs)(struct radeon_winsys* winsys, + const char* file, + const char* function, + int line); + + /* Flush the CS. */ + void (*flush_cs)(struct radeon_winsys* winsys); + + /* winsys flush - callback from winsys when flush required */ + void (*set_flush_cb)(struct radeon_winsys *winsys, + void (*flush_cb)(void *), void *data); + + void (*reset_bos)(struct radeon_winsys *winsys); +}; + +#endif diff --git a/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.c b/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.c deleted file mode 100644 index f038bfa40ef..00000000000 --- a/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.c +++ /dev/null @@ -1,41 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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: Keith Whitwell <keithw-at-tungstengraphics-dot-com> - */ - -#include "radeon_winsys_softpipe.h" - -struct pipe_context *radeon_create_softpipe(struct pipe_winsys* winsys) -{ - struct pipe_screen *pipe_screen; - - pipe_screen = softpipe_create_screen(winsys); - - return softpipe_create(pipe_screen); -} diff --git a/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.h b/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.h deleted file mode 100644 index 04740e41a51..00000000000 --- a/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright © 2008 Jérôme Glisse - * 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: - * Jérôme Glisse <[email protected]> - */ -#ifndef RADEON_WINSYS_SOFTPIPE_H -#define RADEON_WINSYS_SOFTPIPE_H - -#include <stdio.h> - -#include "pipe/p_defines.h" -#include "pipe/p_format.h" - -#include "softpipe/sp_winsys.h" - -#include "util/u_memory.h" - -struct pipe_context *radeon_create_softpipe(struct pipe_winsys* winsys); - -#endif diff --git a/src/gallium/winsys/drm/radeon/dri/SConscript b/src/gallium/winsys/drm/radeon/dri/SConscript index aea987a3aca..c4989d1b595 100644 --- a/src/gallium/winsys/drm/radeon/dri/SConscript +++ b/src/gallium/winsys/drm/radeon/dri/SConscript @@ -13,5 +13,5 @@ drivers = [ env.SharedLibrary( target ='radeon_dri.so', source = COMMON_GALLIUM_SOURCES, - LIBS = st_dri + radeonwinsys + mesa + drivers + auxiliaries + env['LIBS'], + LIBS = st_dri + radeonwinsys + mesa + drivers + gallium + env['LIBS'], ) diff --git a/src/gallium/winsys/drm/radeon/python/SConscript b/src/gallium/winsys/drm/radeon/python/SConscript index 3200fd8d1b0..91cae986975 100644 --- a/src/gallium/winsys/drm/radeon/python/SConscript +++ b/src/gallium/winsys/drm/radeon/python/SConscript @@ -29,5 +29,5 @@ if env['platform'] == 'linux': env.SharedLibrary( target ='_gallium', source = sources, - LIBS = [pyst] + drivers + auxiliaries + env['LIBS'], + LIBS = [pyst] + drivers + gallium + env['LIBS'], ) diff --git a/src/gallium/winsys/drm/radeon/xorg/Makefile b/src/gallium/winsys/drm/radeon/xorg/Makefile index 9fa16dab24c..0eb1b3988f3 100644 --- a/src/gallium/winsys/drm/radeon/xorg/Makefile +++ b/src/gallium/winsys/drm/radeon/xorg/Makefile @@ -1,11 +1,16 @@ -TARGET = modesetting_drv.so -CFILES = $(wildcard ./*.c) -OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES)) -GALLIUMDIR = ../../../.. TOP = ../../../../../.. + +GALLIUMDIR = $(TOP)/src/gallium + +TARGET = radeong_drv.so + +CFILES = $(wildcard ./*.c) + include ${TOP}/configs/current +OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES)) + CFLAGS = -DHAVE_CONFIG_H \ -g -Wall -Wimplicit-function-declaration -fPIC \ $(shell pkg-config --cflags pixman-1 xorg-server libdrm xproto) \ @@ -24,16 +29,21 @@ LIBS = \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(GALLIUM_AUXILIARIES) +TARGET_STAGING = $(TOP)/$(LIB_DIR)/gallium/$(TARGET) ############################################# +all default: $(TARGET) $(TARGET_STAGING) - -all default: $(TARGET) - -$(TARGET): $(OBJECTS) Makefile $(GALLIUMDIR)/state_trackers/xorg/libxorgtracker.a +$(TARGET): $(OBJECTS) Makefile $(GALLIUMDIR)/state_trackers/xorg/libxorgtracker.a $(LIBS) $(TOP)/bin/mklib -noprefix -o $@ \ $(OBJECTS) $(LIBS) $(shell pkg-config --libs libdrm) -ldrm_radeon +$(TOP)/$(LIB_DIR)/gallium: + mkdir -p $@ + +$(TARGET_STAGING): $(TARGET) $(TOP)/$(LIB_DIR)/gallium + $(INSTALL) $(TARGET) $(TOP)/$(LIB_DIR)/gallium + clean: rm -rf $(OBJECTS) $(TARGET) diff --git a/src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c b/src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c index 837f2aa8fec..bb76cc03499 100644 --- a/src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c +++ b/src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c @@ -53,7 +53,7 @@ static PciChipsets radeon_xorg_pci_devices[] = { }; static XF86ModuleVersionInfo radeon_xorg_version = { - "modesetting", + "radeong", MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, @@ -69,9 +69,9 @@ static XF86ModuleVersionInfo radeon_xorg_version = { * Xorg driver exported structures */ -_X_EXPORT DriverRec modesetting = { +_X_EXPORT DriverRec radeong = { 1, - "modesetting", + "radeong", radeon_xorg_identify, NULL, xorg_tracker_available_options, @@ -84,7 +84,7 @@ _X_EXPORT DriverRec modesetting = { static MODULESETUPPROTO(radeon_xorg_setup); -_X_EXPORT XF86ModuleData modesettingModuleData = { +_X_EXPORT XF86ModuleData radeongModuleData = { &radeon_xorg_version, radeon_xorg_setup, NULL @@ -103,7 +103,7 @@ radeon_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin) */ if (!setupDone) { setupDone = 1; - xf86AddDriver(&modesetting, module, HaveDriverFuncs); + xf86AddDriver(&radeong, module, HaveDriverFuncs); /* * The return value must be non-NULL on success even though there @@ -120,7 +120,7 @@ radeon_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin) static void radeon_xorg_identify(int flags) { - xf86PrintChipsets("modesetting", "Driver for Modesetting Kernel Drivers", + xf86PrintChipsets("radeong", "Driver for Radeon Gallium with KMS", radeon_xorg_chipsets); } @@ -135,8 +135,8 @@ radeon_xorg_pci_probe(DriverPtr driver, NULL, NULL, NULL, NULL, NULL); if (scrn != NULL) { scrn->driverVersion = 1; - scrn->driverName = "radeon"; - scrn->name = "modesetting"; + scrn->driverName = "radeong"; + scrn->name = "radeong"; scrn->Probe = NULL; entity = xf86GetEntityInfo(entity_num); diff --git a/src/gallium/winsys/drm/vmware/Makefile b/src/gallium/winsys/drm/vmware/Makefile new file mode 100644 index 00000000000..2ae6dead5c1 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/Makefile @@ -0,0 +1,12 @@ +# src/gallium/winsys/drm/vmware/Makefile +TOP = ../../../../.. +include $(TOP)/configs/current + +SUBDIRS = core $(GALLIUM_STATE_TRACKERS_DIRS) + +default install clean: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE) $@) || exit 1; \ + fi \ + done diff --git a/src/gallium/winsys/drm/vmware/SConscript b/src/gallium/winsys/drm/vmware/SConscript new file mode 100644 index 00000000000..06e6d5be9ca --- /dev/null +++ b/src/gallium/winsys/drm/vmware/SConscript @@ -0,0 +1,11 @@ +Import('*') + +SConscript(['core/SConscript',]) + +if 'mesa' in env['statetrackers']: + + SConscript(['dri/SConscript']) + +if 'xorg' in env['statetrackers']: + + SConscript(['xorg/SConscript']) diff --git a/src/gallium/winsys/drm/vmware/core/Makefile b/src/gallium/winsys/drm/vmware/core/Makefile new file mode 100644 index 00000000000..a52957c1a5b --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/Makefile @@ -0,0 +1,35 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBNAME = svgadrm + +C_SOURCES = \ + vmw_buffer.c \ + vmw_context.c \ + vmw_fence.c \ + vmw_screen.c \ + vmw_screen_dri.c \ + vmw_screen_ioctl.c \ + vmw_screen_pools.c \ + vmw_screen_svga.c \ + vmw_surface.c + +LIBRARY_INCLUDES = \ + -I$(TOP)/src/gallium/drivers/svga \ + -I$(TOP)/src/gallium/drivers/svga/include \ + -I$(GALLIUM)/src/mesa/drivers/dri/common \ + -I$(GALLIUM)/include \ + -I$(GALLIUM)/include/GL/internal \ + -I$(GALLIUM)/src/mesa \ + -I$(GALLIUM)/src/mesa/main \ + -I$(GALLIUM)/src/mesa/glapi \ + -I$(GALLIUM)/src/egl/main \ + -I$(GALLIUM)/src/egl/drivers/dri \ + $(shell pkg-config libdrm --cflags-only-I) + +LIBRARY_DEFINES = \ + -std=gnu99 -fvisibility=hidden \ + -DHAVE_STDINT_H -D_FILE_OFFSET_BITS=64 \ + $(shell pkg-config libdrm --cflags-only-other) + +include ../../../../Makefile.template diff --git a/src/gallium/winsys/drm/vmware/core/SConscript b/src/gallium/winsys/drm/vmware/core/SConscript new file mode 100644 index 00000000000..edaf9458bee --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/SConscript @@ -0,0 +1,39 @@ +Import('*') + +env = env.Clone() + +if env['gcc']: + env.Append(CCFLAGS = ['-fvisibility=hidden']) + env.Append(CPPDEFINES = [ + 'HAVE_STDINT_H', + 'HAVE_SYS_TYPES_H', + '-D_FILE_OFFSET_BITS=64', + ]) + +env.Prepend(CPPPATH = [ + 'include', + '#/src/gallium/drivers/svga', + '#/src/gallium/drivers/svga/include', +]) + +env.Append(CPPDEFINES = [ +]) + +sources = [ + 'vmw_buffer.c', + 'vmw_context.c', + 'vmw_fence.c', + 'vmw_screen.c', + 'vmw_screen_dri.c', + 'vmw_screen_ioctl.c', + 'vmw_screen_pools.c', + 'vmw_screen_svga.c', + 'vmw_surface.c', +] + +svgadrm = env.ConvenienceLibrary( + target = 'svgadrm', + source = sources, +) + +Export('svgadrm') diff --git a/src/gallium/winsys/drm/vmware/core/vmw_buffer.c b/src/gallium/winsys/drm/vmware/core/vmw_buffer.c new file mode 100644 index 00000000000..b812fb59d39 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_buffer.c @@ -0,0 +1,274 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + +/** + * @file + * SVGA buffer manager for Guest Memory Regions (GMRs). + * + * GMRs are used for pixel and vertex data upload/download to/from the virtual + * SVGA hardware. There is a limited number of GMRs available, and + * creating/destroying them is also a slow operation so we must suballocate + * them. + * + * This file implements a pipebuffer library's buffer manager, so that we can + * use pipepbuffer's suballocation, fencing, and debugging facilities with GMRs. + * + * @author Jose Fonseca <[email protected]> + */ + + +#include "svga_cmd.h" + +#include "pipe/p_inlines.h" +#include "util/u_memory.h" +#include "pipebuffer/pb_buffer.h" +#include "pipebuffer/pb_bufmgr.h" + +#include "svga_winsys.h" + +#include "vmw_screen.h" +#include "vmw_buffer.h" + + +struct vmw_gmr_bufmgr; + + +struct vmw_gmr_buffer +{ + struct pb_buffer base; + + struct vmw_gmr_bufmgr *mgr; + + struct vmw_region *region; + void *map; + +#ifdef DEBUG + struct pipe_fence_handle *last_fence; +#endif +}; + + +extern const struct pb_vtbl vmw_gmr_buffer_vtbl; + + +static INLINE struct vmw_gmr_buffer * +vmw_gmr_buffer(struct pb_buffer *buf) +{ + assert(buf); + assert(buf->vtbl == &vmw_gmr_buffer_vtbl); + return (struct vmw_gmr_buffer *)buf; +} + + +struct vmw_gmr_bufmgr +{ + struct pb_manager base; + + struct vmw_winsys_screen *vws; +}; + + +static INLINE struct vmw_gmr_bufmgr * +vmw_gmr_bufmgr(struct pb_manager *mgr) +{ + assert(mgr); + return (struct vmw_gmr_bufmgr *)mgr; +} + + +static void +vmw_gmr_buffer_destroy(struct pb_buffer *_buf) +{ + struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf); + +#ifdef DEBUG + if(buf->last_fence) { + struct svga_winsys_screen *sws = &buf->mgr->vws->base; + assert(sws->fence_signalled(sws, buf->last_fence, 0) == 0); + } +#endif + + vmw_ioctl_region_unmap(buf->region); + + vmw_ioctl_region_destroy(buf->region); + + FREE(buf); +} + + +static void * +vmw_gmr_buffer_map(struct pb_buffer *_buf, + unsigned flags) +{ + struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf); + return buf->map; +} + + +static void +vmw_gmr_buffer_unmap(struct pb_buffer *_buf) +{ + /* Do nothing */ + (void)_buf; +} + + +static void +vmw_gmr_buffer_get_base_buffer(struct pb_buffer *buf, + struct pb_buffer **base_buf, + unsigned *offset) +{ + *base_buf = buf; + *offset = 0; +} + + +static enum pipe_error +vmw_gmr_buffer_validate( struct pb_buffer *_buf, + struct pb_validate *vl, + unsigned flags ) +{ + /* Always pinned */ + return PIPE_OK; +} + + +static void +vmw_gmr_buffer_fence( struct pb_buffer *_buf, + struct pipe_fence_handle *fence ) +{ + /* We don't need to do anything, as the pipebuffer library + * will take care of delaying the destruction of fenced buffers */ +#ifdef DEBUG + struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf); + if(fence) + buf->last_fence = fence; +#endif +} + + +const struct pb_vtbl vmw_gmr_buffer_vtbl = { + vmw_gmr_buffer_destroy, + vmw_gmr_buffer_map, + vmw_gmr_buffer_unmap, + vmw_gmr_buffer_validate, + vmw_gmr_buffer_fence, + vmw_gmr_buffer_get_base_buffer +}; + + +static struct pb_buffer * +vmw_gmr_bufmgr_create_buffer(struct pb_manager *_mgr, + pb_size size, + const struct pb_desc *desc) +{ + struct vmw_gmr_bufmgr *mgr = vmw_gmr_bufmgr(_mgr); + struct vmw_winsys_screen *vws = mgr->vws; + struct vmw_gmr_buffer *buf; + + buf = CALLOC_STRUCT(vmw_gmr_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 = &vmw_gmr_buffer_vtbl; + buf->mgr = mgr; + + buf->region = vmw_ioctl_region_create(vws, size); + if(!buf->region) + goto error2; + + buf->map = vmw_ioctl_region_map(buf->region); + if(!buf->map) + goto error3; + + return &buf->base; + +error3: + vmw_ioctl_region_destroy(buf->region); +error2: + FREE(buf); +error1: + return NULL; +} + + +static void +vmw_gmr_bufmgr_flush(struct pb_manager *mgr) +{ + /* No-op */ +} + + +static void +vmw_gmr_bufmgr_destroy(struct pb_manager *_mgr) +{ + struct vmw_gmr_bufmgr *mgr = vmw_gmr_bufmgr(_mgr); + FREE(mgr); +} + + +struct pb_manager * +vmw_gmr_bufmgr_create(struct vmw_winsys_screen *vws) +{ + struct vmw_gmr_bufmgr *mgr; + + mgr = CALLOC_STRUCT(vmw_gmr_bufmgr); + if(!mgr) + return NULL; + + mgr->base.destroy = vmw_gmr_bufmgr_destroy; + mgr->base.create_buffer = vmw_gmr_bufmgr_create_buffer; + mgr->base.flush = vmw_gmr_bufmgr_flush; + + mgr->vws = vws; + + return &mgr->base; +} + + +boolean +vmw_gmr_bufmgr_region_ptr(struct pb_buffer *buf, + struct SVGAGuestPtr *ptr) +{ + struct pb_buffer *base_buf; + unsigned offset = 0; + struct vmw_gmr_buffer *gmr_buf; + + pb_get_base_buffer( buf, &base_buf, &offset ); + + gmr_buf = vmw_gmr_buffer(base_buf); + if(!gmr_buf) + return FALSE; + + *ptr = vmw_ioctl_region_ptr(gmr_buf->region); + + ptr->offset += offset; + + return TRUE; +} diff --git a/src/gallium/winsys/drm/vmware/core/vmw_buffer.h b/src/gallium/winsys/drm/vmware/core/vmw_buffer.h new file mode 100644 index 00000000000..634bdcabd26 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_buffer.h @@ -0,0 +1,65 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + + +#ifndef VMW_BUFFER_H_ +#define VMW_BUFFER_H_ + + +#include "pipe/p_compiler.h" + +struct SVGAGuestPtr; +struct pb_buffer; +struct pb_manager; +struct svga_winsys_buffer; +struct svga_winsys_surface; +struct vmw_winsys_screen; + + +static INLINE struct pb_buffer * +vmw_pb_buffer(struct svga_winsys_buffer *buffer) +{ + assert(buffer); + return (struct pb_buffer *)buffer; +} + + +static INLINE struct svga_winsys_buffer * +vmw_svga_winsys_buffer(struct pb_buffer *buffer) +{ + assert(buffer); + return (struct svga_winsys_buffer *)buffer; +} + + +struct pb_manager * +vmw_gmr_bufmgr_create(struct vmw_winsys_screen *vws); + +boolean +vmw_gmr_bufmgr_region_ptr(struct pb_buffer *buf, + struct SVGAGuestPtr *ptr); + + +#endif /* VMW_BUFFER_H_ */ diff --git a/src/gallium/winsys/drm/vmware/core/vmw_context.c b/src/gallium/winsys/drm/vmware/core/vmw_context.c new file mode 100644 index 00000000000..b6997588de4 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_context.c @@ -0,0 +1,297 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 "svga_cmd.h" + +#include "util/u_debug.h" +#include "util/u_memory.h" +#include "util/u_debug_stack.h" +#include "pipebuffer/pb_buffer.h" +#include "pipebuffer/pb_validate.h" + +#include "svga_winsys.h" +#include "vmw_context.h" +#include "vmw_screen.h" +#include "vmw_buffer.h" +#include "vmw_surface.h" +#include "vmw_fence.h" + +#define VMW_COMMAND_SIZE (64*1024) +#define VMW_SURFACE_RELOCS (1024) + +#define VMW_MUST_FLUSH_STACK 8 + +struct vmw_svga_winsys_context +{ + struct svga_winsys_context base; + + struct vmw_winsys_screen *vws; + +#ifdef DEBUG + boolean must_flush; + struct debug_stack_frame must_flush_stack[VMW_MUST_FLUSH_STACK]; +#endif + + struct { + uint8_t buffer[VMW_COMMAND_SIZE]; + uint32_t size; + uint32_t used; + uint32_t reserved; + } command; + + struct { + struct vmw_svga_winsys_surface *handles[VMW_SURFACE_RELOCS]; + uint32_t size; + uint32_t used; + uint32_t staged; + uint32_t reserved; + } surface; + + struct pb_validate *validate; + + uint32_t last_fence; +}; + + +static INLINE struct vmw_svga_winsys_context * +vmw_svga_winsys_context(struct svga_winsys_context *swc) +{ + assert(swc); + return (struct vmw_svga_winsys_context *)swc; +} + + +static enum pipe_error +vmw_swc_flush(struct svga_winsys_context *swc, + struct pipe_fence_handle **pfence) +{ + struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); + struct pipe_fence_handle *fence = NULL; + unsigned i; + enum pipe_error ret; + + ret = pb_validate_validate(vswc->validate); + assert(ret == PIPE_OK); + if(ret == PIPE_OK) { + + if (vswc->command.used) + vmw_ioctl_command(vswc->vws, + vswc->command.buffer, + vswc->command.used, + &vswc->last_fence); + + fence = vmw_pipe_fence(vswc->last_fence); + + pb_validate_fence(vswc->validate, fence); + } + + vswc->command.used = 0; + vswc->command.reserved = 0; + + for(i = 0; i < vswc->surface.used + vswc->surface.staged; ++i) { + struct vmw_svga_winsys_surface *vsurf = + vswc->surface.handles[i]; + p_atomic_dec(&vsurf->validated); + vmw_svga_winsys_surface_reference(&vswc->surface.handles[i], NULL); + } + + vswc->surface.used = 0; + vswc->surface.reserved = 0; + +#ifdef DEBUG + vswc->must_flush = FALSE; +#endif + + if(pfence) + *pfence = fence; + + return ret; +} + + +static void * +vmw_swc_reserve(struct svga_winsys_context *swc, + uint32_t nr_bytes, uint32_t nr_relocs ) +{ + struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); + +#ifdef DEBUG + /* Check if somebody forgot to check the previous failure */ + if(vswc->must_flush) { + debug_printf("Forgot to flush:\n"); + debug_backtrace_dump(vswc->must_flush_stack, VMW_MUST_FLUSH_STACK); + assert(!vswc->must_flush); + } +#endif + + assert(nr_bytes <= vswc->command.size); + if(nr_bytes > vswc->command.size) + return NULL; + + if(vswc->command.used + nr_bytes > vswc->command.size || + vswc->surface.used + nr_relocs > vswc->surface.size) { +#ifdef DEBUG + vswc->must_flush = TRUE; + debug_backtrace_capture(vswc->must_flush_stack, 1, + VMW_MUST_FLUSH_STACK); +#endif + return NULL; + } + + assert(vswc->command.used + nr_bytes <= vswc->command.size); + assert(vswc->surface.used + nr_relocs <= vswc->surface.size); + + vswc->command.reserved = nr_bytes; + vswc->surface.reserved = nr_relocs; + vswc->surface.staged = 0; + + return vswc->command.buffer + vswc->command.used; +} + + +static void +vmw_swc_surface_relocation(struct svga_winsys_context *swc, + uint32 *where, + struct svga_winsys_surface *surface, + unsigned flags) +{ + struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); + struct vmw_svga_winsys_surface *vsurf; + + if(!surface) { + *where = SVGA3D_INVALID_ID; + return; + } + + assert(vswc->surface.staged < vswc->surface.reserved); + + vsurf = vmw_svga_winsys_surface(surface); + + *where = vsurf->sid; + + vmw_svga_winsys_surface_reference(&vswc->surface.handles[vswc->surface.used + vswc->surface.staged], vsurf); + p_atomic_inc(&vsurf->validated); + ++vswc->surface.staged; +} + + +static void +vmw_swc_region_relocation(struct svga_winsys_context *swc, + struct SVGAGuestPtr *where, + struct svga_winsys_buffer *buffer, + uint32 offset, + unsigned flags) +{ + struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); + struct SVGAGuestPtr ptr; + struct pb_buffer *buf = vmw_pb_buffer(buffer); + enum pipe_error ret; + + if(!vmw_gmr_bufmgr_region_ptr(buf, &ptr)) + assert(0); + + ptr.offset += offset; + + *where = ptr; + + ret = pb_validate_add_buffer(vswc->validate, buf, flags); + /* TODO: Update pipebuffer to reserve buffers and not fail here */ + assert(ret == PIPE_OK); +} + + +static void +vmw_swc_commit(struct svga_winsys_context *swc) +{ + struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); + + assert(vswc->command.reserved); + assert(vswc->command.used + vswc->command.reserved <= vswc->command.size); + vswc->command.used += vswc->command.reserved; + vswc->command.reserved = 0; + + assert(vswc->surface.staged <= vswc->surface.reserved); + assert(vswc->surface.used + vswc->surface.staged <= vswc->surface.size); + vswc->surface.used += vswc->surface.staged; + vswc->surface.staged = 0; + vswc->surface.reserved = 0; +} + + +static void +vmw_swc_destroy(struct svga_winsys_context *swc) +{ + struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); + unsigned i; + for(i = 0; i < vswc->surface.used; ++i) { + p_atomic_dec(&vswc->surface.handles[i]->validated); + vmw_svga_winsys_surface_reference(&vswc->surface.handles[i], NULL); + } + pb_validate_destroy(vswc->validate); + vmw_ioctl_context_destroy(vswc->vws, swc->cid); + FREE(vswc); +} + + +struct svga_winsys_context * +vmw_svga_winsys_context_create(struct svga_winsys_screen *sws) +{ + struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); + struct vmw_svga_winsys_context *vswc; + + vswc = CALLOC_STRUCT(vmw_svga_winsys_context); + if(!vswc) + return NULL; + + vswc->base.destroy = vmw_swc_destroy; + vswc->base.reserve = vmw_swc_reserve; + vswc->base.surface_relocation = vmw_swc_surface_relocation; + vswc->base.region_relocation = vmw_swc_region_relocation; + vswc->base.commit = vmw_swc_commit; + vswc->base.flush = vmw_swc_flush; + + vswc->base.cid = vmw_ioctl_context_create(vws); + + vswc->vws = vws; + + vswc->command.size = VMW_COMMAND_SIZE; + vswc->surface.size = VMW_SURFACE_RELOCS; + + vswc->validate = pb_validate_create(); + if(!vswc->validate) { + FREE(vswc); + return NULL; + } + + return &vswc->base; +} + + +struct pipe_context * +vmw_svga_context_create(struct pipe_screen *screen) +{ + return svga_context_create(screen); +} diff --git a/src/gallium/winsys/drm/vmware/core/vmw_context.h b/src/gallium/winsys/drm/vmware/core/vmw_context.h new file mode 100644 index 00000000000..305ce9b5bec --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_context.h @@ -0,0 +1,59 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + +/** + * @author Jose Fonseca <[email protected]> + */ + + +#ifndef VMW_CONTEXT_H_ +#define VMW_CONTEXT_H_ + +#include "pipe/p_compiler.h" + +struct svga_winsys_screen; +struct svga_winsys_context; +struct pipe_context; +struct pipe_screen; + +#define VMW_DEBUG 0 + +#if VMW_DEBUG +#define vmw_printf debug_printf +#define VMW_FUNC debug_printf("%s\n", __FUNCTION__) +#else +#define VMW_FUNC +#define vmw_printf(...) +#endif + + +struct svga_winsys_context * +vmw_svga_winsys_context_create(struct svga_winsys_screen *sws); + +struct pipe_context * +vmw_svga_context_create(struct pipe_screen *screen); + + +#endif /* VMW_CONTEXT_H_ */ diff --git a/src/gallium/winsys/drm/vmware/core/vmw_fence.c b/src/gallium/winsys/drm/vmware/core/vmw_fence.c new file mode 100644 index 00000000000..873dd51166c --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_fence.c @@ -0,0 +1,108 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 "util/u_memory.h" +#include "pipebuffer/pb_buffer_fenced.h" + +#include "vmw_screen.h" +#include "vmw_fence.h" + + + +struct vmw_fence_ops +{ + struct pb_fence_ops base; + + struct vmw_winsys_screen *vws; +}; + + +static INLINE struct vmw_fence_ops * +vmw_fence_ops(struct pb_fence_ops *ops) +{ + assert(ops); + return (struct vmw_fence_ops *)ops; +} + + +static void +vmw_fence_ops_fence_reference(struct pb_fence_ops *ops, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + *ptr = fence; +} + + +static int +vmw_fence_ops_fence_signalled(struct pb_fence_ops *ops, + struct pipe_fence_handle *fence, + unsigned flag) +{ + struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws; + (void)flag; + return vmw_ioctl_fence_signalled(vws, vmw_fence(fence)); +} + + +static int +vmw_fence_ops_fence_finish(struct pb_fence_ops *ops, + struct pipe_fence_handle *fence, + unsigned flag) +{ + struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws; + (void)flag; + return vmw_ioctl_fence_finish(vws, vmw_fence(fence)); +} + + +static void +vmw_fence_ops_destroy(struct pb_fence_ops *ops) +{ + FREE(ops); +} + + +struct pb_fence_ops * +vmw_fence_ops_create(struct vmw_winsys_screen *vws) +{ + struct vmw_fence_ops *ops; + + ops = CALLOC_STRUCT(vmw_fence_ops); + if(!ops) + return NULL; + + ops->base.destroy = &vmw_fence_ops_destroy; + ops->base.fence_reference = &vmw_fence_ops_fence_reference; + ops->base.fence_signalled = &vmw_fence_ops_fence_signalled; + ops->base.fence_finish = &vmw_fence_ops_fence_finish; + + ops->vws = vws; + + return &ops->base; +} + + diff --git a/src/gallium/winsys/drm/vmware/core/vmw_fence.h b/src/gallium/winsys/drm/vmware/core/vmw_fence.h new file mode 100644 index 00000000000..5357b4f61de --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_fence.h @@ -0,0 +1,59 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + + +#ifndef VMW_FENCE_H_ +#define VMW_FENCE_H_ + + +#include "pipe/p_compiler.h" + + +struct pipe_fence_handle; +struct pb_fence_ops; +struct vmw_winsys_screen; + + +/** Cast from a pipe_fence_handle pointer into a SVGA fence */ +static INLINE uint32_t +vmw_fence( struct pipe_fence_handle *fence ) +{ + return (uint32_t)(uintptr_t)fence; +} + + +/** Cast from a SVGA fence number to pipe_fence_handle pointer */ +static INLINE struct pipe_fence_handle * +vmw_pipe_fence( uint32_t fence ) +{ + return (struct pipe_fence_handle *)(uintptr_t)fence; +} + + +struct pb_fence_ops * +vmw_fence_ops_create(struct vmw_winsys_screen *vws); + + +#endif /* VMW_FENCE_H_ */ diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen.c b/src/gallium/winsys/drm/vmware/core/vmw_screen.c new file mode 100644 index 00000000000..911eec5e254 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen.c @@ -0,0 +1,74 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 "vmw_screen.h" + +#include "vmw_context.h" + +#include "util/u_memory.h" +#include "pipe/p_compiler.h" + + +/* Called from vmw_drm_create_screen(), creates and initializes the + * vmw_winsys_screen structure, which is the main entity in this + * module. + */ +struct vmw_winsys_screen * +vmw_winsys_create( int fd ) +{ + struct vmw_winsys_screen *vws = CALLOC_STRUCT(vmw_winsys_screen); + if (!vws) + goto out_no_vws; + + vws->ioctl.drm_fd = fd; + + if (!vmw_ioctl_init(vws)) + goto out_no_ioctl; + + if(!vmw_pools_init(vws)) + goto out_no_pools; + + if (!vmw_winsys_screen_init_svga(vws)) + goto out_no_svga; + + return vws; +out_no_svga: + vmw_pools_cleanup(vws); +out_no_pools: + vmw_ioctl_cleanup(vws); +out_no_ioctl: + FREE(vws); +out_no_vws: + return NULL; +} + +void +vmw_winsys_destroy(struct vmw_winsys_screen *vws) +{ + vmw_pools_cleanup(vws); + vmw_ioctl_cleanup(vws); + FREE(vws); +} diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen.h b/src/gallium/winsys/drm/vmware/core/vmw_screen.h new file mode 100644 index 00000000000..a875107370c --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen.h @@ -0,0 +1,134 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + +/** + * @file + * Common definitions for the VMware SVGA winsys. + * + * @author Jose Fonseca <[email protected]> + */ + + +#ifndef VMW_SCREEN_H_ +#define VMW_SCREEN_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + +#include "svga_winsys.h" + +struct pb_manager; +struct vmw_region; + + +struct vmw_winsys_screen +{ + struct svga_winsys_screen base; + + struct { + volatile uint32_t *fifo_map; + uint64_t last_fence; + int drm_fd; + } ioctl; + + struct { + struct pb_manager *gmr; + struct pb_manager *gmr_mm; + struct pb_manager *gmr_fenced; + } pools; +}; + + +static INLINE struct vmw_winsys_screen * +vmw_winsys_screen(struct svga_winsys_screen *base) +{ + return (struct vmw_winsys_screen *)base; +} + +/* */ +uint32 +vmw_ioctl_context_create(struct vmw_winsys_screen *vws); + +void +vmw_ioctl_context_destroy(struct vmw_winsys_screen *vws, + uint32 cid); + +uint32 +vmw_ioctl_surface_create(struct vmw_winsys_screen *vws, + SVGA3dSurfaceFlags flags, + SVGA3dSurfaceFormat format, + SVGA3dSize size, + uint32 numFaces, + uint32 numMipLevels); + +void +vmw_ioctl_surface_destroy(struct vmw_winsys_screen *vws, + uint32 sid); + +void +vmw_ioctl_command(struct vmw_winsys_screen *vws, + void *commands, + uint32_t size, + uint32_t *fence); + +struct vmw_region * +vmw_ioctl_region_create(struct vmw_winsys_screen *vws, uint32_t size); + +void +vmw_ioctl_region_destroy(struct vmw_region *region); + +struct SVGAGuestPtr +vmw_ioctl_region_ptr(struct vmw_region *region); + +void * +vmw_ioctl_region_map(struct vmw_region *region); +void +vmw_ioctl_region_unmap(struct vmw_region *region); + + +int +vmw_ioctl_fence_finish(struct vmw_winsys_screen *vws, + uint32_t fence); + +int +vmw_ioctl_fence_signalled(struct vmw_winsys_screen *vws, + uint32_t fence); + + +/* Initialize parts of vmw_winsys_screen at startup: + */ +boolean vmw_ioctl_init(struct vmw_winsys_screen *vws); +boolean vmw_pools_init(struct vmw_winsys_screen *vws); +boolean vmw_winsys_screen_init_svga(struct vmw_winsys_screen *vws); + +void vmw_ioctl_cleanup(struct vmw_winsys_screen *vws); +void vmw_pools_cleanup(struct vmw_winsys_screen *vws); + +struct vmw_winsys_screen *vmw_winsys_create(int fd); +void vmw_winsys_destroy(struct vmw_winsys_screen *sws); + + +#endif /* VMW_SCREEN_H_ */ diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c b/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c new file mode 100644 index 00000000000..5995eee34ba --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c @@ -0,0 +1,371 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 "pipe/p_compiler.h" +#include "pipe/p_inlines.h" +#include "util/u_memory.h" +#include "vmw_screen.h" + +#include "trace/tr_drm.h" + +#include "vmw_screen.h" +#include "vmw_surface.h" +#include "vmw_fence.h" +#include "vmw_context.h" + +#include <state_tracker/dri1_api.h> +#include <state_tracker/drm_api.h> +#include <vmwgfx_drm.h> +#include <xf86drm.h> + +#include <stdio.h> + +static struct dri1_api dri1_api_hooks; +static struct dri1_api_version ddx_required = { 0, 1, 0 }; +static struct dri1_api_version ddx_compat = { 0, 0, 0 }; +static struct dri1_api_version dri_required = { 4, 0, 0 }; +static struct dri1_api_version dri_compat = { 4, 0, 0 }; +static struct dri1_api_version drm_required = { 0, 1, 0 }; +static struct dri1_api_version drm_compat = { 0, 0, 0 }; + +static boolean +vmw_dri1_check_version(const struct dri1_api_version *cur, + const struct dri1_api_version *required, + const struct dri1_api_version *compat, + const char component[]) +{ + if (cur->major > required->major && cur->major <= compat->major) + return TRUE; + if (cur->major == required->major && cur->minor >= required->minor) + return TRUE; + + fprintf(stderr, "%s version failure.\n", component); + fprintf(stderr, "%s version is %d.%d.%d and this driver can only work\n" + "with versions %d.%d.x through %d.x.x.\n", + component, + cur->major, + cur->minor, + cur->patch_level, required->major, required->minor, compat->major); + return FALSE; +} + +/* This is actually the entrypoint to the entire driver, called by the + * libGL (or EGL, or ...) code via the drm_api_hooks table at the + * bottom of the file. + */ +static struct pipe_screen * +vmw_drm_create_screen(struct drm_api *drm_api, + int fd, + struct drm_create_screen_arg *arg) +{ + struct vmw_winsys_screen *vws; + struct pipe_screen *screen; + struct dri1_create_screen_arg *dri1; + + if (arg != NULL) { + switch (arg->mode) { + case DRM_CREATE_NORMAL: + break; + case DRM_CREATE_DRI1: + dri1 = (struct dri1_create_screen_arg *)arg; + if (!vmw_dri1_check_version(&dri1->ddx_version, &ddx_required, + &ddx_compat, "ddx - driver api")) + return NULL; + if (!vmw_dri1_check_version(&dri1->dri_version, &dri_required, + &dri_compat, "dri info")) + return NULL; + if (!vmw_dri1_check_version(&dri1->drm_version, &drm_required, + &drm_compat, "vmwgfx drm driver")) + return NULL; + dri1->api = &dri1_api_hooks; + break; + default: + return NULL; + } + } + + vws = vmw_winsys_create( fd ); + if (!vws) + goto out_no_vws; + + screen = svga_screen_create( &vws->base ); + if (!screen) + goto out_no_screen; + + return screen; + + /* Failure cases: + */ +out_no_screen: + vmw_winsys_destroy( vws ); + +out_no_vws: + return NULL; +} + +static INLINE boolean +vmw_dri1_intersect_src_bbox(struct drm_clip_rect *dst, + int dst_x, + int dst_y, + const struct drm_clip_rect *src, + const struct drm_clip_rect *bbox) +{ + int xy1; + int xy2; + + xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 : + (int)bbox->x1 + dst_x; + xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 : + (int)bbox->x2 + dst_x; + if (xy1 >= xy2 || xy1 < 0) + return FALSE; + + dst->x1 = xy1; + dst->x2 = xy2; + + xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 : + (int)bbox->y1 + dst_y; + xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 : + (int)bbox->y2 + dst_y; + if (xy1 >= xy2 || xy1 < 0) + return FALSE; + + dst->y1 = xy1; + dst->y2 = xy2; + return TRUE; +} + +/** + * No fancy get-surface-from-sarea stuff here. + * Just use the present blit. + */ + +static void +vmw_dri1_present_locked(struct pipe_context *locked_pipe, + struct pipe_surface *surf, + const struct drm_clip_rect *rect, + unsigned int num_clip, + int x_draw, int y_draw, + const struct drm_clip_rect *bbox, + struct pipe_fence_handle **p_fence) +{ + struct svga_winsys_surface *srf = + svga_screen_texture_get_winsys_surface(surf->texture); + struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf); + struct vmw_winsys_screen *vws = + vmw_winsys_screen(svga_winsys_screen(locked_pipe->screen)); + struct drm_clip_rect clip; + int i; + struct + { + SVGA3dCmdHeader header; + SVGA3dCmdPresent body; + SVGA3dCopyRect rect; + } cmd; + boolean visible = FALSE; + uint32_t fence_seq = 0; + + VMW_FUNC; + cmd.header.id = SVGA_3D_CMD_PRESENT; + cmd.header.size = sizeof cmd.body + sizeof cmd.rect; + cmd.body.sid = vsrf->sid; + + for (i = 0; i < num_clip; ++i) { + if (!vmw_dri1_intersect_src_bbox(&clip, x_draw, y_draw, rect++, bbox)) + continue; + + cmd.rect.x = clip.x1; + cmd.rect.y = clip.y1; + cmd.rect.w = clip.x2 - clip.x1; + cmd.rect.h = clip.y2 - clip.y1; + cmd.rect.srcx = (int)clip.x1 - x_draw; + cmd.rect.srcy = (int)clip.y1 - y_draw; + + vmw_printf("%s: Clip %d x %d y %d w %d h %d srcx %d srcy %d\n", + __FUNCTION__, + i, + cmd.rect.x, + cmd.rect.y, + cmd.rect.w, cmd.rect.h, cmd.rect.srcx, cmd.rect.srcy); + + vmw_ioctl_command(vws, &cmd, sizeof cmd.header + cmd.header.size, + &fence_seq); + visible = TRUE; + } + + *p_fence = (visible) ? vmw_pipe_fence(fence_seq) : NULL; + vmw_svga_winsys_surface_reference(&vsrf, NULL); +} + +/** + * FIXME: We'd probably want to cache these buffers in the + * screen, based on handle. + */ + +static struct pipe_buffer * +vmw_drm_buffer_from_handle(struct drm_api *drm_api, + struct pipe_screen *screen, + const char *name, + unsigned handle) +{ + struct vmw_svga_winsys_surface *vsrf; + struct svga_winsys_surface *ssrf; + struct vmw_winsys_screen *vws = + vmw_winsys_screen(svga_winsys_screen(screen)); + struct pipe_buffer *buf; + union drm_vmw_surface_reference_arg arg; + struct drm_vmw_surface_arg *req = &arg.req; + struct drm_vmw_surface_create_req *rep = &arg.rep; + int ret; + int i; + + /** + * The vmware device specific handle is the hardware SID. + * FIXME: We probably want to move this to the ioctl implementations. + */ + + memset(&arg, 0, sizeof(arg)); + req->sid = handle; + + ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_REF_SURFACE, + &arg, sizeof(arg)); + + if (ret) { + fprintf(stderr, "Failed referencing shared surface. SID %d.\n" + "Error %d (%s).\n", + handle, ret, strerror(-ret)); + return NULL; + } + + if (rep->mip_levels[0] != 1) { + fprintf(stderr, "Incorrect number of mipmap levels on shared surface." + " SID %d, levels %d\n", + handle, rep->mip_levels[0]); + goto out_mip; + } + + for (i=1; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { + if (rep->mip_levels[i] != 0) { + fprintf(stderr, "Incorrect number of faces levels on shared surface." + " SID %d, face %d present.\n", + handle, i); + goto out_mip; + } + } + + vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface); + if (!vsrf) + goto out_mip; + + pipe_reference_init(&vsrf->refcnt, 1); + p_atomic_set(&vsrf->validated, 0); + vsrf->sid = handle; + ssrf = svga_winsys_surface(vsrf); + buf = svga_screen_buffer_wrap_surface(screen, rep->format, ssrf); + if (!buf) + vmw_svga_winsys_surface_reference(&vsrf, NULL); + + return buf; + out_mip: + vmw_ioctl_surface_destroy(vws, handle); + return NULL; +} + +static struct pipe_texture * +vmw_drm_texture_from_handle(struct drm_api *drm_api, + struct pipe_screen *screen, + struct pipe_texture *templat, + const char *name, + unsigned stride, + unsigned handle) +{ + struct pipe_buffer *buffer; + buffer = vmw_drm_buffer_from_handle(drm_api, screen, name, handle); + + if (!buffer) + return NULL; + + return screen->texture_blanket(screen, templat, &stride, buffer); +} + +static boolean +vmw_drm_handle_from_buffer(struct drm_api *drm_api, + struct pipe_screen *screen, + struct pipe_buffer *buffer, + unsigned *handle) +{ + struct svga_winsys_surface *surface = + svga_screen_buffer_get_winsys_surface(buffer); + struct vmw_svga_winsys_surface *vsrf; + + if (!surface) + return FALSE; + + vsrf = vmw_svga_winsys_surface(surface); + *handle = vsrf->sid; + vmw_svga_winsys_surface_reference(&vsrf, NULL); + return TRUE; +} + +static boolean +vmw_drm_handle_from_texture(struct drm_api *drm_api, + struct pipe_screen *screen, + struct pipe_texture *texture, + unsigned *stride, + unsigned *handle) +{ + struct pipe_buffer *buffer; + + if (!svga_screen_buffer_from_texture(texture, &buffer, stride)) + return FALSE; + + return vmw_drm_handle_from_buffer(drm_api, screen, buffer, handle); +} + +static struct pipe_context* +vmw_drm_create_context(struct drm_api *drm_api, + struct pipe_screen *screen) +{ + return vmw_svga_context_create(screen); +} + +static struct dri1_api dri1_api_hooks = { + .front_srf_locked = NULL, + .present_locked = vmw_dri1_present_locked +}; + +static struct drm_api vmw_drm_api_hooks = { + .create_screen = vmw_drm_create_screen, + .create_context = vmw_drm_create_context, + .texture_from_shared_handle = vmw_drm_texture_from_handle, + .shared_handle_from_texture = vmw_drm_handle_from_texture, + .local_handle_from_texture = vmw_drm_handle_from_texture, +}; + +struct drm_api* drm_api_create() +{ + return trace_drm_create(&vmw_drm_api_hooks); +} diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen_ioctl.c b/src/gallium/winsys/drm/vmware/core/vmw_screen_ioctl.c new file mode 100644 index 00000000000..ccd0b418a16 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_ioctl.c @@ -0,0 +1,513 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + +/** + * @file + * + * Wrappers for DRM ioctl functionlaity used by the rest of the vmw + * drm winsys. + * + * Based on svgaicd_escape.c + */ + + +#include "svga_cmd.h" +#include "util/u_memory.h" +#include "util/u_math.h" +#include "svgadump/svga_dump.h" +#include "vmw_screen.h" +#include "vmw_context.h" +#include "xf86drm.h" +#include "vmwgfx_drm.h" + +#include <sys/mman.h> +#include <errno.h> +#include <unistd.h> + +struct vmw_region +{ + SVGAGuestPtr ptr; + uint32_t handle; + uint64_t map_handle; + void *data; + uint32_t map_count; + int drm_fd; + uint32_t size; +}; + +static void +vmw_check_last_cmd(struct vmw_winsys_screen *vws) +{ + static uint32_t buffer[16384]; + struct drm_vmw_fifo_debug_arg arg; + int ret; + + return; + memset(&arg, 0, sizeof(arg)); + arg.debug_buffer = (unsigned long)buffer; + arg.debug_buffer_size = 65536; + + ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_FIFO_DEBUG, + &arg, sizeof(arg)); + + if (ret) { + debug_printf("%s Ioctl error: \"%s\".\n", __FUNCTION__, strerror(-ret)); + return; + } + + if (arg.did_not_fit) { + debug_printf("%s Command did not fit completely.\n", __FUNCTION__); + } + + svga_dump_commands(buffer, arg.used_size); +} + +static void +vmw_ioctl_fifo_unmap(struct vmw_winsys_screen *vws, void *mapping) +{ + VMW_FUNC; + (void)munmap(mapping, getpagesize()); +} + + +static void * +vmw_ioctl_fifo_map(struct vmw_winsys_screen *vws, + uint32_t fifo_offset ) +{ + void *map; + + VMW_FUNC; + + map = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, + vws->ioctl.drm_fd, fifo_offset); + + if (map == MAP_FAILED) { + debug_printf("Map failed %s\n", strerror(errno)); + return NULL; + } + + vmw_printf("Fifo (min) is 0x%08x\n", ((uint32_t *) map)[SVGA_FIFO_MIN]); + + return map; +} + +uint32 +vmw_ioctl_context_create(struct vmw_winsys_screen *vws) +{ + struct drm_vmw_context_arg c_arg; + int ret; + + VMW_FUNC; + + ret = drmCommandRead(vws->ioctl.drm_fd, DRM_VMW_CREATE_CONTEXT, + &c_arg, sizeof(c_arg)); + + if (ret) + return -1; + + vmw_check_last_cmd(vws); + vmw_printf("Context id is %d\n", c_arg.cid); + + return c_arg.cid; +} + +void +vmw_ioctl_context_destroy(struct vmw_winsys_screen *vws, uint32 cid) +{ + struct drm_vmw_context_arg c_arg; + + VMW_FUNC; + + memset(&c_arg, 0, sizeof(c_arg)); + c_arg.cid = cid; + + (void)drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_UNREF_CONTEXT, + &c_arg, sizeof(c_arg)); + + vmw_check_last_cmd(vws); +} + +uint32 +vmw_ioctl_surface_create(struct vmw_winsys_screen *vws, + SVGA3dSurfaceFlags flags, + SVGA3dSurfaceFormat format, + SVGA3dSize size, + uint32_t numFaces, uint32_t numMipLevels) +{ + union drm_vmw_surface_create_arg s_arg; + struct drm_vmw_surface_create_req *req = &s_arg.req; + struct drm_vmw_surface_arg *rep = &s_arg.rep; + struct drm_vmw_size sizes[DRM_VMW_MAX_SURFACE_FACES* + DRM_VMW_MAX_MIP_LEVELS]; + struct drm_vmw_size *cur_size; + uint32_t iFace; + uint32_t iMipLevel; + int ret; + + vmw_printf("%s flags %d format %d\n", __FUNCTION__, flags, format); + + memset(&s_arg, 0, sizeof(s_arg)); + req->flags = (uint32_t) flags; + req->format = (uint32_t) format; + req->shareable = 1; + + assert(numFaces * numMipLevels < DRM_VMW_MAX_SURFACE_FACES* + DRM_VMW_MAX_MIP_LEVELS); + cur_size = sizes; + for (iFace = 0; iFace < numFaces; ++iFace) { + SVGA3dSize mipSize = size; + + req->mip_levels[iFace] = numMipLevels; + for (iMipLevel = 0; iMipLevel < numMipLevels; ++iMipLevel) { + cur_size->width = mipSize.width; + cur_size->height = mipSize.height; + cur_size->depth = mipSize.depth; + mipSize.width = MAX2(mipSize.width >> 1, 1); + mipSize.height = MAX2(mipSize.height >> 1, 1); + mipSize.depth = MAX2(mipSize.depth >> 1, 1); + cur_size++; + } + } + for (iFace = numFaces; iFace < SVGA3D_MAX_SURFACE_FACES; ++iFace) { + req->mip_levels[iFace] = 0; + } + + req->size_addr = (unsigned long)&sizes; + + ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_CREATE_SURFACE, + &s_arg, sizeof(s_arg)); + + if (ret) + return -1; + + vmw_printf("Surface id is %d\n", rep->sid); + vmw_check_last_cmd(vws); + + return rep->sid; +} + +void +vmw_ioctl_surface_destroy(struct vmw_winsys_screen *vws, uint32 sid) +{ + struct drm_vmw_surface_arg s_arg; + + VMW_FUNC; + + memset(&s_arg, 0, sizeof(s_arg)); + s_arg.sid = sid; + + (void)drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_UNREF_SURFACE, + &s_arg, sizeof(s_arg)); + vmw_check_last_cmd(vws); + +} + +void +vmw_ioctl_command(struct vmw_winsys_screen *vws, void *commands, uint32_t size, + uint32_t * pfence) +{ + struct drm_vmw_execbuf_arg arg; + struct drm_vmw_fence_rep rep; + int ret; + +#ifdef DEBUG + { + static boolean firsttime = TRUE; + static boolean debug = FALSE; + static boolean skip = FALSE; + if (firsttime) { + debug = debug_get_bool_option("SVGA_DUMP_CMD", FALSE); + skip = debug_get_bool_option("SVGA_SKIP_CMD", FALSE); + } + if (debug) { + VMW_FUNC; + svga_dump_commands(commands, size); + } + firsttime = FALSE; + if (skip) { + size = 0; + } + } +#endif + + memset(&arg, 0, sizeof(arg)); + memset(&rep, 0, sizeof(rep)); + + rep.error = -EFAULT; + arg.fence_rep = (unsigned long)&rep; + arg.commands = (unsigned long)commands; + arg.command_size = size; + + do { + ret = drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg)); + } while(ret == -ERESTART); + if (ret) { + debug_printf("%s error %s.\n", __FUNCTION__, strerror(-ret)); + } + if (rep.error) { + + /* + * Kernel has synced and put the last fence sequence in the FIFO + * register. + */ + + if (rep.error == -EFAULT) + rep.fence_seq = vws->ioctl.fifo_map[SVGA_FIFO_FENCE]; + + debug_printf("%s Fence error %s.\n", __FUNCTION__, + strerror(-rep.error)); + } + + vws->ioctl.last_fence = rep.fence_seq; + + if (pfence) + *pfence = rep.fence_seq; + vmw_check_last_cmd(vws); + +} + + +struct vmw_region * +vmw_ioctl_region_create(struct vmw_winsys_screen *vws, uint32_t size) +{ + struct vmw_region *region; + union drm_vmw_alloc_dmabuf_arg arg; + struct drm_vmw_alloc_dmabuf_req *req = &arg.req; + struct drm_vmw_dmabuf_rep *rep = &arg.rep; + int ret; + + vmw_printf("%s: size = %u\n", __FUNCTION__, size); + + region = CALLOC_STRUCT(vmw_region); + if (!region) + goto out_err1; + + memset(&arg, 0, sizeof(arg)); + req->size = size; + do { + ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_ALLOC_DMABUF, &arg, + sizeof(arg)); + } while (ret == -ERESTART); + + if (ret) { + debug_printf("IOCTL failed %d: %s\n", ret, strerror(-ret)); + goto out_err1; + } + + region->ptr.gmrId = rep->cur_gmr_id; + region->ptr.offset = rep->cur_gmr_offset; + region->data = NULL; + region->handle = rep->handle; + region->map_handle = rep->map_handle; + region->map_count = 0; + region->size = size; + region->drm_fd = vws->ioctl.drm_fd; + + vmw_printf(" gmrId = %u, offset = %u\n", + region->ptr.gmrId, region->ptr.offset); + + return region; + + out_err1: + FREE(region); + return NULL; +} + +void +vmw_ioctl_region_destroy(struct vmw_region *region) +{ + struct drm_vmw_unref_dmabuf_arg arg; + + vmw_printf("%s: gmrId = %u, offset = %u\n", __FUNCTION__, + region->ptr.gmrId, region->ptr.offset); + + if (region->data) { + munmap(region->data, region->size); + region->data = NULL; + } + + memset(&arg, 0, sizeof(arg)); + arg.handle = region->handle; + drmCommandWrite(region->drm_fd, DRM_VMW_UNREF_DMABUF, &arg, sizeof(arg)); + + FREE(region); +} + +SVGAGuestPtr +vmw_ioctl_region_ptr(struct vmw_region *region) +{ + return region->ptr; +} + +void * +vmw_ioctl_region_map(struct vmw_region *region) +{ + void *map; + + vmw_printf("%s: gmrId = %u, offset = %u\n", __FUNCTION__, + region->ptr.gmrId, region->ptr.offset); + + if (region->data == NULL) { + map = mmap(NULL, region->size, PROT_READ | PROT_WRITE, MAP_SHARED, + region->drm_fd, region->map_handle); + if (map == MAP_FAILED) { + debug_printf("%s: Map failed.\n", __FUNCTION__); + return NULL; + } + + region->data = map; + } + + ++region->map_count; + + return region->data; +} + +void +vmw_ioctl_region_unmap(struct vmw_region *region) +{ + vmw_printf("%s: gmrId = %u, offset = %u\n", __FUNCTION__, + region->ptr.gmrId, region->ptr.offset); + --region->map_count; +} + + +int +vmw_ioctl_fence_signalled(struct vmw_winsys_screen *vws, + uint32_t fence) +{ + uint32_t expected; + uint32_t current; + + assert(fence); + if(!fence) + return 0; + + expected = fence; + current = vws->ioctl.fifo_map[SVGA_FIFO_FENCE]; + + if ((int32)(current - expected) >= 0) + return 0; /* fence passed */ + else + return -1; +} + + +static void +vmw_ioctl_sync(struct vmw_winsys_screen *vws, + uint32_t fence) +{ + uint32_t cur_fence; + struct drm_vmw_fence_wait_arg arg; + int ret; + + vmw_printf("%s: fence = %lu\n", __FUNCTION__, + (unsigned long)fence); + + cur_fence = vws->ioctl.fifo_map[SVGA_FIFO_FENCE]; + vmw_printf("%s: Fence id read is 0x%08x\n", __FUNCTION__, + (unsigned int)cur_fence); + + if ((cur_fence - fence) < (1 << 24)) + return; + + memset(&arg, 0, sizeof(arg)); + arg.sequence = fence; + + do { + ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_FENCE_WAIT, &arg, + sizeof(arg)); + } while (ret == -ERESTART); +} + + +int +vmw_ioctl_fence_finish(struct vmw_winsys_screen *vws, + uint32_t fence) +{ + assert(fence); + + if(fence) { + if(vmw_ioctl_fence_signalled(vws, fence) != 0) { + vmw_ioctl_sync(vws, fence); + } + } + + return 0; +} + + +boolean +vmw_ioctl_init(struct vmw_winsys_screen *vws) +{ + struct drm_vmw_getparam_arg gp_arg; + int ret; + + VMW_FUNC; + + memset(&gp_arg, 0, sizeof(gp_arg)); + gp_arg.param = DRM_VMW_PARAM_3D; + ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM, + &gp_arg, sizeof(gp_arg)); + if (ret || gp_arg.value == 0) { + debug_printf("No 3D enabled (%i, %s)\n", ret, strerror(-ret)); + goto out_err1; + } + + memset(&gp_arg, 0, sizeof(gp_arg)); + gp_arg.param = DRM_VMW_PARAM_FIFO_OFFSET; + ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM, + &gp_arg, sizeof(gp_arg)); + + if (ret) { + debug_printf("GET_PARAM on %d returned %d: %s\n", + vws->ioctl.drm_fd, ret, strerror(-ret)); + goto out_err1; + } + + vmw_printf("Offset to map is 0x%08llx\n", + (unsigned long long)gp_arg.value); + + vws->ioctl.fifo_map = vmw_ioctl_fifo_map(vws, gp_arg.value); + if (vws->ioctl.fifo_map == NULL) + goto out_err1; + + vmw_printf("%s OK\n", __FUNCTION__); + return TRUE; + + out_err1: + debug_printf("%s Failed\n", __FUNCTION__); + return FALSE; +} + + + +void +vmw_ioctl_cleanup(struct vmw_winsys_screen *vws) +{ + VMW_FUNC; + + vmw_ioctl_fifo_unmap(vws, (void *)vws->ioctl.fifo_map); +} diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen_pools.c b/src/gallium/winsys/drm/vmware/core/vmw_screen_pools.c new file mode 100644 index 00000000000..b1c24b0cb6a --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_pools.c @@ -0,0 +1,79 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 "vmw_screen.h" + +#include "vmw_buffer.h" +#include "vmw_fence.h" + +#include "pipebuffer/pb_buffer.h" +#include "pipebuffer/pb_bufmgr.h" + +void +vmw_pools_cleanup(struct vmw_winsys_screen *vws) +{ + if(vws->pools.gmr_fenced) + vws->pools.gmr_fenced->destroy(vws->pools.gmr_fenced); + + /* gmr_mm pool is already destroyed above */ + + if(vws->pools.gmr) + vws->pools.gmr->destroy(vws->pools.gmr); +} + + +boolean +vmw_pools_init(struct vmw_winsys_screen *vws) +{ + vws->pools.gmr = vmw_gmr_bufmgr_create(vws); + if(!vws->pools.gmr) + goto error; + + vws->pools.gmr_mm = mm_bufmgr_create(vws->pools.gmr, + 16*1024*1024, + 12 /* 4096 alignment */); + if(!vws->pools.gmr_mm) + goto error; + + vws->pools.gmr_fenced = fenced_bufmgr_create( + vws->pools.gmr_mm, + vmw_fence_ops_create(vws)); + +#ifdef DEBUG + vws->pools.gmr_fenced = pb_debug_manager_create(vws->pools.gmr_fenced, + 4096, + 4096); +#endif + if(!vws->pools.gmr_fenced) + goto error; + + return TRUE; + +error: + vmw_pools_cleanup(vws); + return FALSE; +} + diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen_svga.c b/src/gallium/winsys/drm/vmware/core/vmw_screen_svga.c new file mode 100644 index 00000000000..d7d008859b3 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_svga.c @@ -0,0 +1,295 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + +/** + * @file + * This file implements the SVGA interface into this winsys, defined + * in drivers/svga/svga_winsys.h. + * + * @author Keith Whitwell + * @author Jose Fonseca + */ + + +#include "svga_cmd.h" +#include "svga3d_caps.h" + +#include "pipe/p_inlines.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "pipebuffer/pb_buffer.h" +#include "pipebuffer/pb_bufmgr.h" +#include "svga_winsys.h" +#include "vmw_context.h" +#include "vmw_screen.h" +#include "vmw_surface.h" +#include "vmw_buffer.h" +#include "vmw_fence.h" + + +static struct svga_winsys_buffer * +vmw_svga_winsys_buffer_create(struct svga_winsys_screen *sws, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); + struct pb_desc desc; + struct pb_manager *provider; + struct pb_buffer *buffer; + + memset(&desc, 0, sizeof desc); + desc.alignment = alignment; + desc.usage = usage; + + provider = vws->pools.gmr_fenced; + + assert(provider); + buffer = provider->create_buffer(provider, size, &desc); + if(!buffer) + return NULL; + + return vmw_svga_winsys_buffer(buffer); +} + + +static void * +vmw_svga_winsys_buffer_map(struct svga_winsys_screen *sws, + struct svga_winsys_buffer *buf, + unsigned flags) +{ + (void)sws; + return pb_map(vmw_pb_buffer(buf), flags); +} + + +static void +vmw_svga_winsys_buffer_unmap(struct svga_winsys_screen *sws, + struct svga_winsys_buffer *buf) +{ + (void)sws; + pb_unmap(vmw_pb_buffer(buf)); +} + + +static void +vmw_svga_winsys_buffer_destroy(struct svga_winsys_screen *sws, + struct svga_winsys_buffer *buf) +{ + struct pb_buffer *pbuf = vmw_pb_buffer(buf); + (void)sws; + pb_reference(&pbuf, NULL); +} + + +static void +vmw_svga_winsys_fence_reference(struct svga_winsys_screen *sws, + struct pipe_fence_handle **pdst, + struct pipe_fence_handle *src) +{ + (void)sws; + *pdst = src; +} + + +static int +vmw_svga_winsys_fence_signalled(struct svga_winsys_screen *sws, + struct pipe_fence_handle *fence, + unsigned flag) +{ + struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); + (void)flag; + return vmw_ioctl_fence_signalled(vws, vmw_fence(fence)); +} + + +static int +vmw_svga_winsys_fence_finish(struct svga_winsys_screen *sws, + struct pipe_fence_handle *fence, + unsigned flag) +{ + struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); + (void)flag; + return vmw_ioctl_fence_finish(vws, vmw_fence(fence)); +} + + + +static struct svga_winsys_surface * +vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws, + SVGA3dSurfaceFlags flags, + SVGA3dSurfaceFormat format, + SVGA3dSize size, + uint32 numFaces, + uint32 numMipLevels) +{ + struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); + struct vmw_svga_winsys_surface *surface; + + surface = CALLOC_STRUCT(vmw_svga_winsys_surface); + if(!surface) + goto no_surface; + + pipe_reference_init(&surface->refcnt, 1); + p_atomic_set(&surface->validated, 0); + surface->screen = vws; + surface->sid = vmw_ioctl_surface_create(vws, + flags, format, size, + numFaces, numMipLevels); + if(surface->sid == SVGA3D_INVALID_ID) + goto no_sid; + + return svga_winsys_surface(surface); + +no_sid: + FREE(surface); +no_surface: + return NULL; +} + + +static boolean +vmw_svga_winsys_surface_is_flushed(struct svga_winsys_screen *sws, + struct svga_winsys_surface *surface) +{ + struct vmw_svga_winsys_surface *vsurf = vmw_svga_winsys_surface(surface); + return (p_atomic_read(&vsurf->validated) == 0); +} + + +static void +vmw_svga_winsys_surface_ref(struct svga_winsys_screen *sws, + struct svga_winsys_surface **pDst, + struct svga_winsys_surface *src) +{ + struct vmw_svga_winsys_surface *d_vsurf = vmw_svga_winsys_surface(*pDst); + struct vmw_svga_winsys_surface *s_vsurf = vmw_svga_winsys_surface(src); + + vmw_svga_winsys_surface_reference(&d_vsurf, s_vsurf); + *pDst = svga_winsys_surface(d_vsurf); +} + + +static void +vmw_svga_winsys_destroy(struct svga_winsys_screen *sws) +{ + struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); + + vmw_winsys_destroy(vws); +} + + +static boolean +vmw_svga_winsys_get_cap(struct svga_winsys_screen *sws, + SVGA3dDevCapIndex index, + SVGA3dDevCapResult *result) +{ + struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); + const uint32 *capsBlock; + const SVGA3dCapsRecord *capsRecord = NULL; + uint32 offset; + const SVGA3dCapPair *capArray; + int numCaps, first, last; + + if(!vws->ioctl.fifo_map) + return FALSE; + + if(vws->ioctl.fifo_map[SVGA_FIFO_3D_HWVERSION] < SVGA3D_HWVERSION_WS6_B1) + return FALSE; + + /* + * Search linearly through the caps block records for the specified type. + */ + capsBlock = (const uint32 *)&vws->ioctl.fifo_map[SVGA_FIFO_3D_CAPS]; + for (offset = 0; capsBlock[offset] != 0; offset += capsBlock[offset]) { + const SVGA3dCapsRecord *record; + assert(offset < SVGA_FIFO_3D_CAPS_SIZE); + record = (const SVGA3dCapsRecord *) (capsBlock + offset); + if ((record->header.type >= SVGA3DCAPS_RECORD_DEVCAPS_MIN) && + (record->header.type <= SVGA3DCAPS_RECORD_DEVCAPS_MAX) && + (!capsRecord || (record->header.type > capsRecord->header.type))) { + capsRecord = record; + } + } + + if(!capsRecord) + return FALSE; + + /* + * Calculate the number of caps from the size of the record. + */ + capArray = (const SVGA3dCapPair *) capsRecord->data; + numCaps = (int) ((capsRecord->header.length * sizeof(uint32) - + sizeof capsRecord->header) / (2 * sizeof(uint32))); + + /* + * Binary-search for the cap with the specified index. + */ + for (first = 0, last = numCaps - 1; first <= last; ) { + int mid = (first + last) / 2; + + if ((SVGA3dDevCapIndex) capArray[mid][0] == index) { + /* + * Found it. + */ + result->u = capArray[mid][1]; + return TRUE; + } + + /* + * Divide and conquer. + */ + if ((SVGA3dDevCapIndex) capArray[mid][0] > index) { + last = mid - 1; + } else { + first = mid + 1; + } + } + + return FALSE; +} + + +boolean +vmw_winsys_screen_init_svga(struct vmw_winsys_screen *vws) +{ + vws->base.destroy = vmw_svga_winsys_destroy; + vws->base.get_cap = vmw_svga_winsys_get_cap; + vws->base.context_create = vmw_svga_winsys_context_create; + vws->base.surface_create = vmw_svga_winsys_surface_create; + vws->base.surface_is_flushed = vmw_svga_winsys_surface_is_flushed; + vws->base.surface_reference = vmw_svga_winsys_surface_ref; + vws->base.buffer_create = vmw_svga_winsys_buffer_create; + vws->base.buffer_map = vmw_svga_winsys_buffer_map; + vws->base.buffer_unmap = vmw_svga_winsys_buffer_unmap; + vws->base.buffer_destroy = vmw_svga_winsys_buffer_destroy; + vws->base.fence_reference = vmw_svga_winsys_fence_reference; + vws->base.fence_signalled = vmw_svga_winsys_fence_signalled; + vws->base.fence_finish = vmw_svga_winsys_fence_finish; + + return TRUE; +} + + diff --git a/src/gallium/winsys/drm/vmware/core/vmw_surface.c b/src/gallium/winsys/drm/vmware/core/vmw_surface.c new file mode 100644 index 00000000000..5f1b9ad5770 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_surface.c @@ -0,0 +1,61 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 "svga_cmd.h" +#include "util/u_debug.h" +#include "util/u_memory.h" + +#include "vmw_surface.h" +#include "vmw_screen.h" + +void +vmw_svga_winsys_surface_reference(struct vmw_svga_winsys_surface **pdst, + struct vmw_svga_winsys_surface *src) +{ + struct pipe_reference *src_ref; + struct pipe_reference *dst_ref; + struct vmw_svga_winsys_surface *dst; + + if(pdst == NULL || *pdst == src) + return; + + dst = *pdst; + + src_ref = src ? &src->refcnt : NULL; + dst_ref = dst ? &dst->refcnt : NULL; + + if (pipe_reference(dst_ref, src_ref)) { + vmw_ioctl_surface_destroy(dst->screen, dst->sid); +#ifdef DEBUG + /* to detect dangling pointers */ + assert(p_atomic_read(&dst->validated) == 0); + dst->sid = SVGA3D_INVALID_ID; +#endif + FREE(dst); + } + + *pdst = src; +} diff --git a/src/gallium/winsys/drm/vmware/core/vmw_surface.h b/src/gallium/winsys/drm/vmware/core/vmw_surface.h new file mode 100644 index 00000000000..340cc1532e0 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmw_surface.h @@ -0,0 +1,79 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + +/** + * @file + * Surfaces for VMware SVGA winsys. + * + * @author Jose Fonseca <[email protected]> + */ + + +#ifndef VMW_SURFACE_H_ +#define VMW_SURFACE_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_atomic.h" +#include "pipe/p_refcnt.h" + +#define VMW_MAX_PRESENTS 3 + + + +struct vmw_svga_winsys_surface +{ + struct pipe_atomic validated; + struct pipe_reference refcnt; + + struct vmw_winsys_screen *screen; + uint32_t sid; + + /* FIXME: make this thread safe */ + unsigned next_present_no; + uint32_t present_fences[VMW_MAX_PRESENTS]; +}; + + +static INLINE struct svga_winsys_surface * +svga_winsys_surface(struct vmw_svga_winsys_surface *surf) +{ + assert(!surf || surf->sid != SVGA3D_INVALID_ID); + return (struct svga_winsys_surface *)surf; +} + + +static INLINE struct vmw_svga_winsys_surface * +vmw_svga_winsys_surface(struct svga_winsys_surface *surf) +{ + return (struct vmw_svga_winsys_surface *)surf; +} + + +void +vmw_svga_winsys_surface_reference(struct vmw_svga_winsys_surface **pdst, + struct vmw_svga_winsys_surface *src); + +#endif /* VMW_SURFACE_H_ */ diff --git a/src/gallium/winsys/drm/vmware/core/vmwgfx_drm.h b/src/gallium/winsys/drm/vmware/core/vmwgfx_drm.h new file mode 100644 index 00000000000..2be7e1249b6 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/core/vmwgfx_drm.h @@ -0,0 +1,574 @@ +/************************************************************************** + * + * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA + * 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 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 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. + * + **************************************************************************/ + +#ifndef __VMWGFX_DRM_H__ +#define __VMWGFX_DRM_H__ + +#define DRM_VMW_MAX_SURFACE_FACES 6 +#define DRM_VMW_MAX_MIP_LEVELS 24 + +#define DRM_VMW_EXT_NAME_LEN 128 + +#define DRM_VMW_GET_PARAM 0 +#define DRM_VMW_ALLOC_DMABUF 1 +#define DRM_VMW_UNREF_DMABUF 2 +#define DRM_VMW_CURSOR_BYPASS 3 +/* guarded by DRM_VMW_PARAM_NUM_STREAMS != 0*/ +#define DRM_VMW_CONTROL_STREAM 4 +#define DRM_VMW_CLAIM_STREAM 5 +#define DRM_VMW_UNREF_STREAM 6 +/* guarded by DRM_VMW_PARAM_3D == 1 */ +#define DRM_VMW_CREATE_CONTEXT 7 +#define DRM_VMW_UNREF_CONTEXT 8 +#define DRM_VMW_CREATE_SURFACE 9 +#define DRM_VMW_UNREF_SURFACE 10 +#define DRM_VMW_REF_SURFACE 11 +#define DRM_VMW_EXECBUF 12 +#define DRM_VMW_FIFO_DEBUG 13 +#define DRM_VMW_FENCE_WAIT 14 + + +/*************************************************************************/ +/** + * DRM_VMW_GET_PARAM - get device information. + * + * DRM_VMW_PARAM_FIFO_OFFSET: + * Offset to use to map the first page of the FIFO read-only. + * The fifo is mapped using the mmap() system call on the drm device. + * + * DRM_VMW_PARAM_OVERLAY_IOCTL: + * Does the driver support the overlay ioctl. + */ + +#define DRM_VMW_PARAM_NUM_STREAMS 0 +#define DRM_VMW_PARAM_NUM_FREE_STREAMS 1 +#define DRM_VMW_PARAM_3D 2 +#define DRM_VMW_PARAM_FIFO_OFFSET 3 + + +/** + * struct drm_vmw_getparam_arg + * + * @value: Returned value. //Out + * @param: Parameter to query. //In. + * + * Argument to the DRM_VMW_GET_PARAM Ioctl. + */ + +struct drm_vmw_getparam_arg { + uint64_t value; + uint32_t param; + uint32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_EXTENSION - Query device extensions. + */ + +/** + * struct drm_vmw_extension_rep + * + * @exists: The queried extension exists. + * @driver_ioctl_offset: Ioctl number of the first ioctl in the extension. + * @driver_sarea_offset: Offset to any space in the DRI SAREA + * used by the extension. + * @major: Major version number of the extension. + * @minor: Minor version number of the extension. + * @pl: Patch level version number of the extension. + * + * Output argument to the DRM_VMW_EXTENSION Ioctl. + */ + +struct drm_vmw_extension_rep { + int32_t exists; + uint32_t driver_ioctl_offset; + uint32_t driver_sarea_offset; + uint32_t major; + uint32_t minor; + uint32_t pl; + uint32_t pad64; +}; + +/** + * union drm_vmw_extension_arg + * + * @extension - Ascii name of the extension to be queried. //In + * @rep - Reply as defined above. //Out + * + * Argument to the DRM_VMW_EXTENSION Ioctl. + */ + +union drm_vmw_extension_arg { + char extension[DRM_VMW_EXT_NAME_LEN]; + struct drm_vmw_extension_rep rep; +}; + +/*************************************************************************/ +/** + * DRM_VMW_CREATE_CONTEXT - Create a host context. + * + * Allocates a device unique context id, and queues a create context command + * for the host. Does not wait for host completion. + */ + +/** + * struct drm_vmw_context_arg + * + * @cid: Device unique context ID. + * + * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl. + * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl. + */ + +struct drm_vmw_context_arg { + int32_t cid; + uint32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_UNREF_CONTEXT - Create a host context. + * + * Frees a global context id, and queues a destroy host command for the host. + * Does not wait for host completion. The context ID can be used directly + * in the command stream and shows up as the same context ID on the host. + */ + +/*************************************************************************/ +/** + * DRM_VMW_CREATE_SURFACE - Create a host suface. + * + * Allocates a device unique surface id, and queues a create surface command + * for the host. Does not wait for host completion. The surface ID can be + * used directly in the command stream and shows up as the same surface + * ID on the host. + */ + +/** + * struct drm_wmv_surface_create_req + * + * @flags: Surface flags as understood by the host. + * @format: Surface format as understood by the host. + * @mip_levels: Number of mip levels for each face. + * An unused face should have 0 encoded. + * @size_addr: Address of a user-space array of sruct drm_vmw_size + * cast to an uint64_t for 32-64 bit compatibility. + * The size of the array should equal the total number of mipmap levels. + * @shareable: Boolean whether other clients (as identified by file descriptors) + * may reference this surface. + * + * Input data to the DRM_VMW_CREATE_SURFACE Ioctl. + * Output data from the DRM_VMW_REF_SURFACE Ioctl. + */ + +struct drm_vmw_surface_create_req { + uint32_t flags; + uint32_t format; + uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES]; + uint64_t size_addr; + int32_t shareable; + uint32_t pad64; +}; + +/** + * struct drm_wmv_surface_arg + * + * @sid: Surface id of created surface or surface to destroy or reference. + * + * Output data from the DRM_VMW_CREATE_SURFACE Ioctl. + * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl. + * Input argument to the DRM_VMW_REF_SURFACE Ioctl. + */ + +struct drm_vmw_surface_arg { + int32_t sid; + uint32_t pad64; +}; + +/** + * struct drm_vmw_size ioctl. + * + * @width - mip level width + * @height - mip level height + * @depth - mip level depth + * + * Description of a mip level. + * Input data to the DRM_WMW_CREATE_SURFACE Ioctl. + */ + +struct drm_vmw_size { + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t pad64; +}; + +/** + * union drm_vmw_surface_create_arg + * + * @rep: Output data as described above. + * @req: Input data as described above. + * + * Argument to the DRM_VMW_CREATE_SURFACE Ioctl. + */ + +union drm_vmw_surface_create_arg { + struct drm_vmw_surface_arg rep; + struct drm_vmw_surface_create_req req; +}; + +/*************************************************************************/ +/** + * DRM_VMW_REF_SURFACE - Reference a host surface. + * + * Puts a reference on a host surface with a give sid, as previously + * returned by the DRM_VMW_CREATE_SURFACE ioctl. + * A reference will make sure the surface isn't destroyed while we hold + * it and will allow the calling client to use the surface ID in the command + * stream. + * + * On successful return, the Ioctl returns the surface information given + * in the DRM_VMW_CREATE_SURFACE ioctl. + */ + +/** + * union drm_vmw_surface_reference_arg + * + * @rep: Output data as described above. + * @req: Input data as described above. + * + * Argument to the DRM_VMW_REF_SURFACE Ioctl. + */ + +union drm_vmw_surface_reference_arg { + struct drm_vmw_surface_create_req rep; + struct drm_vmw_surface_arg req; +}; + +/*************************************************************************/ +/** + * DRM_VMW_UNREF_SURFACE - Unreference a host surface. + * + * Clear a reference previously put on a host surface. + * When all references are gone, including the one implicitly placed + * on creation, + * a destroy surface command will be queued for the host. + * Does not wait for completion. + */ + +/*************************************************************************/ +/** + * DRM_VMW_EXECBUF + * + * Submit a command buffer for execution on the host, and return a + * fence sequence that when signaled, indicates that the command buffer has + * executed. + */ + +/** + * struct drm_vmw_execbuf_arg + * + * @commands: User-space address of a command buffer cast to an uint64_t. + * @command-size: Size in bytes of the command buffer. + * @fence_rep: User-space address of a struct drm_vmw_fence_rep cast to an + * uint64_t. + * + * Argument to the DRM_VMW_EXECBUF Ioctl. + */ + +struct drm_vmw_execbuf_arg { + uint64_t commands; + uint32_t command_size; + uint32_t pad64; + uint64_t fence_rep; +}; + +/** + * struct drm_vmw_fence_rep + * + * @fence_seq: Fence sequence associated with a command submission. + * @error: This member should've been set to -EFAULT on submission. + * The following actions should be take on completion: + * error == -EFAULT: Fence communication failed. The host is synchronized. + * Use the last fence id read from the FIFO fence register. + * error != 0 && error != -EFAULT: + * Fence submission failed. The host is synchronized. Use the fence_seq member. + * error == 0: All is OK, The host may not be synchronized. + * Use the fence_seq member. + * + * Input / Output data to the DRM_VMW_EXECBUF Ioctl. + */ + +struct drm_vmw_fence_rep { + uint64_t fence_seq; + int32_t error; + uint32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_ALLOC_DMABUF + * + * Allocate a DMA buffer that is visible also to the host. + * NOTE: The buffer is + * identified by a handle and an offset, which are private to the guest, but + * useable in the command stream. The guest kernel may translate these + * and patch up the command stream accordingly. In the future, the offset may + * be zero at all times, or it may disappear from the interface before it is + * fixed. + * + * The DMA buffer may stay user-space mapped in the guest at all times, + * and is thus suitable for sub-allocation. + * + * DMA buffers are mapped using the mmap() syscall on the drm device. + */ + +/** + * struct drm_vmw_alloc_dmabuf_req + * + * @size: Required minimum size of the buffer. + * + * Input data to the DRM_VMW_ALLOC_DMABUF Ioctl. + */ + +struct drm_vmw_alloc_dmabuf_req { + uint32_t size; + uint32_t pad64; +}; + +/** + * struct drm_vmw_dmabuf_rep + * + * @map_handle: Offset to use in the mmap() call used to map the buffer. + * @handle: Handle unique to this buffer. Used for unreferencing. + * @cur_gmr_id: GMR id to use in the command stream when this buffer is + * referenced. See not above. + * @cur_gmr_offset: Offset to use in the command stream when this buffer is + * referenced. See note above. + * + * Output data from the DRM_VMW_ALLOC_DMABUF Ioctl. + */ + +struct drm_vmw_dmabuf_rep { + uint64_t map_handle; + uint32_t handle; + uint32_t cur_gmr_id; + uint32_t cur_gmr_offset; + uint32_t pad64; +}; + +/** + * union drm_vmw_dmabuf_arg + * + * @req: Input data as described above. + * @rep: Output data as described above. + * + * Argument to the DRM_VMW_ALLOC_DMABUF Ioctl. + */ + +union drm_vmw_alloc_dmabuf_arg { + struct drm_vmw_alloc_dmabuf_req req; + struct drm_vmw_dmabuf_rep rep; +}; + +/*************************************************************************/ +/** + * DRM_VMW_UNREF_DMABUF - Free a DMA buffer. + * + */ + +/** + * struct drm_vmw_unref_dmabuf_arg + * + * @handle: Handle indicating what buffer to free. Obtained from the + * DRM_VMW_ALLOC_DMABUF Ioctl. + * + * Argument to the DRM_VMW_UNREF_DMABUF Ioctl. + */ + +struct drm_vmw_unref_dmabuf_arg { + uint32_t handle; + uint32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_FIFO_DEBUG - Get last FIFO submission. + * + * This IOCTL copies the last FIFO submission directly out of the FIFO buffer. + */ + +/** + * struct drm_vmw_fifo_debug_arg + * + * @debug_buffer: User space address of a debug_buffer cast to an uint64_t //In + * @debug_buffer_size: Size in bytes of debug buffer //In + * @used_size: Number of bytes copied to the buffer // Out + * @did_not_fit: Boolean indicating that the fifo contents did not fit. //Out + * + * Argument to the DRM_VMW_FIFO_DEBUG Ioctl. + */ + +struct drm_vmw_fifo_debug_arg { + uint64_t debug_buffer; + uint32_t debug_buffer_size; + uint32_t used_size; + int32_t did_not_fit; + uint32_t pad64; +}; + +struct drm_vmw_fence_wait_arg { + uint64_t sequence; + uint64_t kernel_cookie; + int32_t cookie_valid; + int32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_CONTROL_STREAM - Control overlays, aka streams. + * + * This IOCTL controls the overlay units of the svga device. + * The SVGA overlay units does not work like regular hardware units in + * that they do not automaticaly read back the contents of the given dma + * buffer. But instead only read back for each call to this ioctl, and + * at any point between this call being made and a following call that + * either changes the buffer or disables the stream. + */ + +/** + * struct drm_vmw_rect + * + * Defines a rectangle. Used in the overlay ioctl to define + * source and destination rectangle. + */ + +struct drm_vmw_rect { + int32_t x; + int32_t y; + uint32_t w; + uint32_t h; +}; + +/** + * struct drm_vmw_control_stream_arg + * + * @stream_id: Stearm to control + * @enabled: If false all following arguments are ignored. + * @handle: Handle to buffer for getting data from. + * @format: Format of the overlay as understood by the host. + * @width: Width of the overlay. + * @height: Height of the overlay. + * @size: Size of the overlay in bytes. + * @pitch: Array of pitches, the two last are only used for YUV12 formats. + * @offset: Offset from start of dma buffer to overlay. + * @src: Source rect, must be within the defined area above. + * @dst: Destination rect, x and y may be negative. + * + * Argument to the DRM_VMW_CONTROL_STREAM Ioctl. + */ + +struct drm_vmw_control_stream_arg { + uint32_t stream_id; + uint32_t enabled; + + uint32_t flags; + uint32_t color_key; + + uint32_t handle; + uint32_t offset; + int32_t format; + uint32_t size; + uint32_t width; + uint32_t height; + uint32_t pitch[3]; + + uint32_t pad64; + struct drm_vmw_rect src; + struct drm_vmw_rect dst; +}; + +/*************************************************************************/ +/** + * DRM_VMW_CURSOR_BYPASS - Give extra information about cursor bypass. + * + */ + +#define DRM_VMW_CURSOR_BYPASS_ALL (1 << 0) +#define DRM_VMW_CURSOR_BYPASS_FLAGS (1) + +/** + * struct drm_vmw_cursor_bypass_arg + * + * @flags: Flags. + * @crtc_id: Crtc id, only used if DMR_CURSOR_BYPASS_ALL isn't passed. + * @xpos: X position of cursor. + * @ypos: Y position of cursor. + * @xhot: X hotspot. + * @yhot: Y hotspot. + * + * Argument to the DRM_VMW_CURSOR_BYPASS Ioctl. + */ + +struct drm_vmw_cursor_bypass_arg { + uint32_t flags; + uint32_t crtc_id; + int32_t xpos; + int32_t ypos; + int32_t xhot; + int32_t yhot; +}; + +/*************************************************************************/ +/** + * DRM_VMW_CLAIM_STREAM - Claim a single stream. + */ + +/** + * struct drm_vmw_context_arg + * + * @stream_id: Device unique context ID. + * + * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl. + * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl. + */ + +struct drm_vmw_stream_arg { + uint32_t stream_id; + uint32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_UNREF_STREAM - Unclaim a stream. + * + * Return a single stream that was claimed by this process. Also makes + * sure that the stream has been stopped. + */ + +#endif diff --git a/src/gallium/winsys/drm/vmware/dri/Makefile b/src/gallium/winsys/drm/vmware/dri/Makefile new file mode 100644 index 00000000000..8a39e23da6d --- /dev/null +++ b/src/gallium/winsys/drm/vmware/dri/Makefile @@ -0,0 +1,18 @@ + +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBNAME = vmwgfx_dri.so + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ + $(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/svga/libsvga.a + +C_SOURCES = \ + $(COMMON_GALLIUM_SOURCES) + +include ../../Makefile.template + +symlinks: diff --git a/src/gallium/winsys/drm/vmware/dri/SConscript b/src/gallium/winsys/drm/vmware/dri/SConscript new file mode 100644 index 00000000000..84319f91ff1 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/dri/SConscript @@ -0,0 +1,62 @@ +import os +import os.path + +Import('*') + +if env['platform'] == 'linux': + + if env['dri']: + env = env.Clone() + + sources = [ + '#/src/mesa/drivers/dri/common/utils.c', + '#/src/mesa/drivers/dri/common/vblank.c', + '#/src/mesa/drivers/dri/common/dri_util.c', + '#/src/mesa/drivers/dri/common/xmlconfig.c', + ] + + + env.ParseConfig('pkg-config --cflags --libs libdrm') + + env.Prepend(CPPPATH = [ + '#/src/mesa/state_tracker', + '#/src/mesa/drivers/dri/common', + '#/src/mesa/main', + '#/src/mesa/glapi', + '#/src/mesa', + '#/include', + '#/src/gallium/drivers/svga', + '#/src/gallium/drivers/svga/include', + ]) + + env.Append(CPPDEFINES = [ + 'HAVE_STDINT_H', + 'HAVE_SYS_TYPES_H', + ]) + + env.Append(CFLAGS = [ + '-std=gnu99', + '-D_FILE_OFFSET_BITS=64', + ]) + + env.Prepend(LIBPATH = [ + ]) + + env.Prepend(LIBS = [ + trace, + st_dri, + svgadrm, + svga, + mesa, + gallium, + ]) + + # TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions + env.LoadableModule( + target ='vmwgfx_dri.so', + source = sources, + LIBS = env['LIBS'], + SHLIBPREFIX = '', + ) + + diff --git a/src/gallium/winsys/drm/vmware/egl/Makefile b/src/gallium/winsys/drm/vmware/egl/Makefile new file mode 100644 index 00000000000..8e2980c318c --- /dev/null +++ b/src/gallium/winsys/drm/vmware/egl/Makefile @@ -0,0 +1,18 @@ + +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBNAME = EGL_svga.so + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ + $(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/svga/libsvga.a + +C_SOURCES = \ + $(COMMON_GALLIUM_SOURCES) + +include ../../Makefile.template + +symlinks: diff --git a/src/gallium/winsys/drm/vmware/xorg/Makefile b/src/gallium/winsys/drm/vmware/xorg/Makefile new file mode 100644 index 00000000000..49e28ae17f5 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/xorg/Makefile @@ -0,0 +1,71 @@ +TOP = ../../../../../.. + +include $(TOP)/configs/current + +TARGET = vmwgfx_drv.so + +CFILES = \ + vmw_xorg.c \ + vmw_video.c \ + vmw_ioctl.c \ + vmw_screen.c + +OBJECTS = $(patsubst %.c,%.o,$(CFILES)) + +INCLUDES = \ + $(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/gallium + +LIBS = \ + $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \ + $(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/svga/libsvga.a \ + $(GALLIUM_AUXILIARIES) + +LINKS = \ + $(shell pkg-config --libs --silence-errors libkms) \ + $(shell pkg-config --libs libdrm) + +DRIVER_DEFINES = \ + -std=gnu99 \ + -DHAVE_CONFIG_H + +TARGET_STAGING = $(TOP)/$(LIB_DIR)/gallium/$(TARGET) + +############################################# + + + +all default: $(TARGET) $(TARGET_STAGING) + +$(TARGET): $(OBJECTS) Makefile $(LIBS) + $(MKLIB) -noprefix -o $@ $(OBJECTS) $(LIBS) $(LINKS) + +$(TOP)/$(LIB_DIR)/gallium: + mkdir -p $@ + +$(TARGET_STAGING): $(TARGET) $(TOP)/$(LIB_DIR)/gallium + $(INSTALL) $(TARGET) $(TOP)/$(LIB_DIR)/gallium + +clean: + rm -rf $(OBJECTS) $(TARGET) + +install: + $(INSTALL) -d $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) + $(MINSTALL) -m 755 $(TARGET) $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) + + +############################################## + + +.c.o: + $(CC) -c $(CFLAGS) $(INCLUDES) $(DRIVER_DEFINES) $< -o $@ + + +############################################## + +.PHONY = all clean install diff --git a/src/gallium/winsys/drm/vmware/xorg/SConscript b/src/gallium/winsys/drm/vmware/xorg/SConscript new file mode 100644 index 00000000000..1e5d8ff7fed --- /dev/null +++ b/src/gallium/winsys/drm/vmware/xorg/SConscript @@ -0,0 +1,57 @@ +import os.path + +Import('*') + +if env['platform'] == 'linux': + + env = env.Clone() + + env.ParseConfig('pkg-config --cflags --libs libdrm xorg-server') + + env.Prepend(CPPPATH = [ + '#/include', + '#/src/gallium', + '#/src/mesa', + '#/src/gallium/drivers/svga', + '#/src/gallium/drivers/svga/include', + ]) + + env.Append(CPPDEFINES = [ + ]) + + if env['gcc']: + env.Append(CPPDEFINES = [ + 'HAVE_STDINT_H', + 'HAVE_SYS_TYPES_H', + ]) + + env.Append(CFLAGS = [ + '-std=gnu99', + '-D_FILE_OFFSET_BITS=64', + ]) + + env.Prepend(LIBPATH = [ + ]) + + env.Prepend(LIBS = [ + trace, + st_xorg, + svgadrm, + svga, + gallium, + ]) + + sources = [ + 'vmw_ioctl.c', + 'vmw_screen.c', + 'vmw_video.c', + 'vmw_xorg.c', + ] + + # TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions + env.LoadableModule( + target ='vmwgfx_drv.so', + source = sources, + LIBS = env['LIBS'], + SHLIBPREFIX = '', + ) diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_driver.h b/src/gallium/winsys/drm/vmware/xorg/vmw_driver.h new file mode 100644 index 00000000000..3efe851a4be --- /dev/null +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_driver.h @@ -0,0 +1,101 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + +/** + * @file + * Contains the shared resources for VMware Xorg driver + * that sits ontop of the Xorg State Traker. + * + * It is initialized in vmw_screen.c. + * + * @author Jakob Bornecrantz <[email protected]> + */ + +#ifndef VMW_DRIVER_H_ +#define VMW_DRIVER_H_ + +#include "state_trackers/xorg/xorg_tracker.h" + +struct vmw_dma_buffer; + +struct vmw_driver +{ + int fd; + + void *cursor_priv; + + /* vmw_video.c */ + void *video_priv; +}; + +static INLINE struct vmw_driver * +vmw_driver(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + return ms ? (struct vmw_driver *)ms->winsys_priv : NULL; +} + + +/*********************************************************************** + * vmw_video.c + */ + +Bool vmw_video_init(ScrnInfoPtr pScrn, struct vmw_driver *vmw); + +Bool vmw_video_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw); + +void vmw_video_stop_all(ScrnInfoPtr pScrn, struct vmw_driver *vmw); + + +/*********************************************************************** + * vmw_ioctl.c + */ + +int vmw_ioctl_cursor_bypass(struct vmw_driver *vmw, int xhot, int yhot); + +struct vmw_dma_buffer * vmw_ioctl_buffer_create(struct vmw_driver *vmw, + uint32_t size, + unsigned *handle); + +void * vmw_ioctl_buffer_map(struct vmw_driver *vmw, + struct vmw_dma_buffer *buf); + +void vmw_ioctl_buffer_unmap(struct vmw_driver *vmw, + struct vmw_dma_buffer *buf); + +void vmw_ioctl_buffer_destroy(struct vmw_driver *vmw, + struct vmw_dma_buffer *buf); + +int vmw_ioctl_supports_streams(struct vmw_driver *vmw); + +int vmw_ioctl_num_streams(struct vmw_driver *vmw, + uint32_t *ntot, uint32_t *nfree); + +int vmw_ioctl_unref_stream(struct vmw_driver *vmw, uint32_t stream_id); + +int vmw_ioctl_claim_stream(struct vmw_driver *vmw, uint32_t *out); + + +#endif diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_hook.h b/src/gallium/winsys/drm/vmware/xorg/vmw_hook.h new file mode 100644 index 00000000000..224a2d92996 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_hook.h @@ -0,0 +1,39 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + +#ifndef VMW_HOOK_H_ +#define VMW_HOOK_H_ + +#include "state_trackers/xorg/xorg_winsys.h" + + +/*********************************************************************** + * vmw_screen.c + */ + +void vmw_screen_set_functions(ScrnInfoPtr pScrn); + + +#endif diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_ioctl.c b/src/gallium/winsys/drm/vmware/xorg/vmw_ioctl.c new file mode 100644 index 00000000000..ab2b5fadc49 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_ioctl.c @@ -0,0 +1,242 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + +/** + * @file + * Contains the functions for creating dma buffers by calling + * the kernel via driver specific ioctls. + * + * @author Jakob Bornecrantz <[email protected]> + */ + +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H 1 +#endif +#define _FILE_OFFSET_BITS 64 + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/mman.h> +#include "xf86drm.h" +#include "../core/vmwgfx_drm.h" + +#include "vmw_driver.h" +#include "util/u_debug.h" + +struct vmw_dma_buffer +{ + void *data; + unsigned handle; + uint64_t map_handle; + unsigned map_count; + uint32_t size; +}; + +static int +vmw_ioctl_get_param(struct vmw_driver *vmw, uint32_t param, uint64_t *out) +{ + struct drm_vmw_getparam_arg gp_arg; + int ret; + + memset(&gp_arg, 0, sizeof(gp_arg)); + gp_arg.param = param; + ret = drmCommandWriteRead(vmw->fd, DRM_VMW_GET_PARAM, + &gp_arg, sizeof(gp_arg)); + + if (ret == 0) { + *out = gp_arg.value; + } + + return ret; +} + +int +vmw_ioctl_supports_streams(struct vmw_driver *vmw) +{ + uint64_t value; + int ret; + + ret = vmw_ioctl_get_param(vmw, DRM_VMW_PARAM_NUM_STREAMS, &value); + if (ret) + return ret; + + return value ? 0 : -ENOSYS; +} + +int +vmw_ioctl_num_streams(struct vmw_driver *vmw, + uint32_t *ntot, uint32_t *nfree) +{ + uint64_t v1, v2; + int ret; + + ret = vmw_ioctl_get_param(vmw, DRM_VMW_PARAM_NUM_STREAMS, &v1); + if (ret) + return ret; + + ret = vmw_ioctl_get_param(vmw, DRM_VMW_PARAM_NUM_FREE_STREAMS, &v2); + if (ret) + return ret; + + *ntot = (uint32_t)v1; + *nfree = (uint32_t)v2; + + return 0; +} + +int +vmw_ioctl_claim_stream(struct vmw_driver *vmw, uint32_t *out) +{ + struct drm_vmw_stream_arg s_arg; + int ret; + + ret = drmCommandRead(vmw->fd, DRM_VMW_CLAIM_STREAM, + &s_arg, sizeof(s_arg)); + + if (ret) + return -1; + + *out = s_arg.stream_id; + return 0; +} + +int +vmw_ioctl_unref_stream(struct vmw_driver *vmw, uint32_t stream_id) +{ + struct drm_vmw_stream_arg s_arg; + int ret; + + memset(&s_arg, 0, sizeof(s_arg)); + s_arg.stream_id = stream_id; + + ret = drmCommandRead(vmw->fd, DRM_VMW_CLAIM_STREAM, + &s_arg, sizeof(s_arg)); + + return 0; +} + +int +vmw_ioctl_cursor_bypass(struct vmw_driver *vmw, int xhot, int yhot) +{ + struct drm_vmw_cursor_bypass_arg arg; + int ret; + + memset(&arg, 0, sizeof(arg)); + arg.flags = DRM_VMW_CURSOR_BYPASS_ALL; + arg.xhot = xhot; + arg.yhot = yhot; + + ret = drmCommandWrite(vmw->fd, DRM_VMW_CURSOR_BYPASS, + &arg, sizeof(arg)); + + return ret; +} + +struct vmw_dma_buffer * +vmw_ioctl_buffer_create(struct vmw_driver *vmw, uint32_t size, unsigned *handle) +{ + struct vmw_dma_buffer *buf; + union drm_vmw_alloc_dmabuf_arg arg; + struct drm_vmw_alloc_dmabuf_req *req = &arg.req; + struct drm_vmw_dmabuf_rep *rep = &arg.rep; + int ret; + + buf = xcalloc(1, sizeof(*buf)); + if (!buf) + goto err; + + memset(&arg, 0, sizeof(arg)); + req->size = size; + do { + ret = drmCommandWriteRead(vmw->fd, DRM_VMW_ALLOC_DMABUF, &arg, sizeof(arg)); + } while (ret == -ERESTART); + + if (ret) { + debug_printf("IOCTL failed %d: %s\n", ret, strerror(-ret)); + goto err_free; + } + + + buf->data = NULL; + buf->handle = rep->handle; + buf->map_handle = rep->map_handle; + buf->map_count = 0; + buf->size = size; + + *handle = rep->handle; + + return buf; + +err_free: + xfree(buf); +err: + return NULL; +} + +void +vmw_ioctl_buffer_destroy(struct vmw_driver *vmw, struct vmw_dma_buffer *buf) +{ + struct drm_vmw_unref_dmabuf_arg arg; + + if (buf->data) { + munmap(buf->data, buf->size); + buf->data = NULL; + } + + memset(&arg, 0, sizeof(arg)); + arg.handle = buf->handle; + drmCommandWrite(vmw->fd, DRM_VMW_UNREF_DMABUF, &arg, sizeof(arg)); + + xfree(buf); +} + +void * +vmw_ioctl_buffer_map(struct vmw_driver *vmw, struct vmw_dma_buffer *buf) +{ + void *map; + + if (buf->data == NULL) { + map = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, + vmw->fd, buf->map_handle); + if (map == MAP_FAILED) { + debug_printf("%s: Map failed.\n", __FUNCTION__); + return NULL; + } + + buf->data = map; + } + + ++buf->map_count; + + return buf->data; +} + +void +vmw_ioctl_buffer_unmap(struct vmw_driver *vmw, struct vmw_dma_buffer *buf) +{ + --buf->map_count; +} diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_screen.c b/src/gallium/winsys/drm/vmware/xorg/vmw_screen.c new file mode 100644 index 00000000000..7c9757cce95 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_screen.c @@ -0,0 +1,178 @@ +/********************************************************** + * Copyright 2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + +/** + * @file + * Contains the init code for the VMware Xorg driver. + * + * @author Jakob Bornecrantz <[email protected]> + */ + +#include "vmw_hook.h" +#include "vmw_driver.h" + +#include "cursorstr.h" + +/* modified version of crtc functions */ +xf86CrtcFuncsRec vmw_screen_crtc_funcs; + +static void +vmw_screen_cursor_load_argb(xf86CrtcPtr crtc, CARD32 *image) +{ + struct vmw_driver *vmw = modesettingPTR(crtc->scrn)->winsys_priv; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + xf86CrtcFuncsPtr funcs = vmw->cursor_priv; + CursorPtr c = config->cursor; + + /* Run the ioctl before uploading the image */ + vmw_ioctl_cursor_bypass(vmw, c->bits->xhot, c->bits->yhot); + + funcs->load_cursor_argb(crtc, image); +} + +static void +vmw_screen_cursor_init(ScrnInfoPtr pScrn, struct vmw_driver *vmw) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + /* XXX assume that all crtc's have the same function struct */ + + /* Save old struct need to call the old functions as well */ + vmw->cursor_priv = (void*)(config->crtc[0]->funcs); + memcpy(&vmw_screen_crtc_funcs, vmw->cursor_priv, sizeof(xf86CrtcFuncsRec)); + vmw_screen_crtc_funcs.load_cursor_argb = vmw_screen_cursor_load_argb; + + for (i = 0; i < config->num_crtc; i++) + config->crtc[i]->funcs = &vmw_screen_crtc_funcs; +} + +static void +vmw_screen_cursor_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + vmw_ioctl_cursor_bypass(vmw, 0, 0); + + for (i = 0; i < config->num_crtc; i++) + config->crtc[i]->funcs = vmw->cursor_priv; +} + +static Bool +vmw_screen_init(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + struct vmw_driver *vmw; + + vmw = xnfcalloc(sizeof(*vmw), 1); + if (!vmw) + return FALSE; + + vmw->fd = ms->fd; + ms->winsys_priv = vmw; + + vmw_screen_cursor_init(pScrn, vmw); + + /* if gallium is used then we don't need to do anything more. */ + if (ms->screen) + return TRUE; + + vmw_video_init(pScrn, vmw); + + return TRUE; +} + +static Bool +vmw_screen_close(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + struct vmw_driver *vmw = vmw_driver(pScrn); + + if (!vmw) + return TRUE; + + vmw_screen_cursor_close(pScrn, vmw); + + vmw_video_close(pScrn, vmw); + + ms->winsys_priv = NULL; + xfree(vmw); + + return TRUE; +} + +static Bool +vmw_screen_enter_vt(ScrnInfoPtr pScrn) +{ + debug_printf("%s: enter\n", __func__); + + return TRUE; +} + +static Bool +vmw_screen_leave_vt(ScrnInfoPtr pScrn) +{ + struct vmw_driver *vmw = vmw_driver(pScrn); + + debug_printf("%s: enter\n", __func__); + + vmw_video_stop_all(pScrn, vmw); + + return TRUE; +} + +/* + * Functions for setting up hooks into the xorg state tracker + */ + +static Bool (*vmw_screen_pre_init_saved)(ScrnInfoPtr pScrn, int flags) = NULL; + +static Bool +vmw_screen_pre_init(ScrnInfoPtr pScrn, int flags) +{ + modesettingPtr ms; + + pScrn->PreInit = vmw_screen_pre_init_saved; + if (!pScrn->PreInit(pScrn, flags)) + return FALSE; + + ms = modesettingPTR(pScrn); + ms->winsys_screen_init = vmw_screen_init; + ms->winsys_screen_close = vmw_screen_close; + ms->winsys_enter_vt = vmw_screen_enter_vt; + ms->winsys_leave_vt = vmw_screen_leave_vt; + + return TRUE; +} + +void +vmw_screen_set_functions(ScrnInfoPtr pScrn) +{ + assert(!vmw_screen_pre_init_saved); + + vmw_screen_pre_init_saved = pScrn->PreInit; + pScrn->PreInit = vmw_screen_pre_init; +} diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_video.c b/src/gallium/winsys/drm/vmware/xorg/vmw_video.c new file mode 100644 index 00000000000..b065b96346a --- /dev/null +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_video.c @@ -0,0 +1,1068 @@ +/* + * Copyright 2007 by VMware, 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 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * vmwarevideo.c -- + * + * Xv extension support. + * See http://www.xfree86.org/current/DESIGN16.html + * + */ + + +#include "xf86xv.h" +#include "fourcc.h" + +#include "pipe/p_compiler.h" +/* + * We can't incude svga_types.h due to conflicting types for Bool. + */ +typedef int64_t int64; +typedef uint64_t uint64; + +typedef int32_t int32; +typedef uint32_t uint32; + +typedef int16_t int16; +typedef uint16_t uint16; + +typedef int8_t int8; +typedef uint8_t uint8; + +#include "svga/include/svga_reg.h" +#include "svga/include/svga_escape.h" +#include "svga/include/svga_overlay.h" + +#include "vmw_driver.h" + +#include <X11/extensions/Xv.h> + +#include "xf86drm.h" +#include "../core/vmwgfx_drm.h" + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +/* + * Number of videos that can be played simultaneously + */ +#define VMWARE_VID_NUM_PORTS 1 + +/* + * Using a dark shade as the default colorKey + */ +#define VMWARE_VIDEO_COLORKEY 0x100701 + +/* + * Maximum dimensions + */ +#define VMWARE_VID_MAX_WIDTH 2048 +#define VMWARE_VID_MAX_HEIGHT 2048 + +#define VMWARE_VID_NUM_ENCODINGS 1 +static XF86VideoEncodingRec vmwareVideoEncodings[] = +{ + { + 0, + "XV_IMAGE", + VMWARE_VID_MAX_WIDTH, VMWARE_VID_MAX_HEIGHT, + {1, 1} + } +}; + +#define VMWARE_VID_NUM_FORMATS 2 +static XF86VideoFormatRec vmwareVideoFormats[] = +{ + { 16, TrueColor}, + { 24, TrueColor} +}; + +#define VMWARE_VID_NUM_IMAGES 3 +static XF86ImageRec vmwareVideoImages[] = +{ + XVIMAGE_YV12, + XVIMAGE_YUY2, + XVIMAGE_UYVY +}; + +#define VMWARE_VID_NUM_ATTRIBUTES 2 +static XF86AttributeRec vmwareVideoAttributes[] = +{ + { + XvGettable | XvSettable, + 0x000000, + 0xffffff, + "XV_COLORKEY" + }, + { + XvGettable | XvSettable, + 0, + 1, + "XV_AUTOPAINT_COLORKEY" + } +}; + +/* + * Video frames are stored in a circular list of buffers. + * Must be power or two, See vmw_video_port_play. + */ +#define VMWARE_VID_NUM_BUFFERS 1 + +/* + * Defines the structure used to hold and pass video data to the host + */ +struct vmw_video_buffer +{ + unsigned handle; + int size; + void *data; + void *extra_data; + struct vmw_dma_buffer *buf; +}; + + +/** + * Structure representing a single video stream, aka port. + * + * Ports maps one to one to a SVGA stream. Port is just + * what Xv calls a SVGA stream. + */ +struct vmw_video_port +{ + /* + * Function prototype same as XvPutImage. + * + * This is either set to vmw_video_port_init or vmw_video_port_play. + * At init this function is set to port_init. In port_init we set it + * to port_play and call it, after initializing the struct. + */ + int (*play)(ScrnInfoPtr, struct vmw_video_port *, + short, short, short, short, short, + short, short, short, int, unsigned char*, + short, short, RegionPtr); + + /* values to go into the SVGAOverlayUnit */ + uint32 streamId; + uint32 colorKey; + uint32 flags; + + /* round robin of buffers */ + unsigned currBuf; + struct vmw_video_buffer bufs[VMWARE_VID_NUM_BUFFERS]; + + /* properties that applies to all buffers */ + int size; + int pitches[3]; + int offsets[3]; + + /* things for X */ + RegionRec clipBoxes; + Bool isAutoPaintColorkey; +}; + + +/** + * Structure holding all the infromation for video. + */ +struct vmw_video_private +{ + int fd; + + /** ports */ + struct vmw_video_port port[VMWARE_VID_NUM_PORTS]; + + /** Used to store port pointers pointers */ + DevUnion port_ptr[VMWARE_VID_NUM_PORTS]; +}; + + +/* + * Callback functions exported to Xv, prefixed with vmw_xv_*. + */ +static int vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, + short drw_x, short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int image, + unsigned char *buf, short width, short height, + Bool sync, RegionPtr clipBoxes, pointer data, + DrawablePtr dst); +static void vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool Cleanup); +static int vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format, + unsigned short *width, + unsigned short *height, int *pitches, + int *offsets); +static int vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, pointer data); +static int vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 *value, pointer data); +static void vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, + short vid_w, short vid_h, short drw_w, + short drw_h, unsigned int *p_w, + unsigned int *p_h, pointer data); + + +/* + * Local functions. + */ +static XF86VideoAdaptorPtr vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_driver *vmw); + +static int vmw_video_port_init(ScrnInfoPtr pScrn, + struct vmw_video_port *port, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes); +static int vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes); +static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmw_video_port *port); + +static int vmw_video_buffer_alloc(struct vmw_driver *vmw, int size, + struct vmw_video_buffer *out); +static int vmw_video_buffer_free(struct vmw_driver *vmw, + struct vmw_video_buffer *out); + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_init -- + * + * Initializes Xv support. + * + * Results: + * TRUE on success, FALSE on error. + * + * Side effects: + * Xv support is initialized. Memory is allocated for all supported + * video streams. + * + *----------------------------------------------------------------------------- + */ + +Bool +vmw_video_init(ScrnInfoPtr pScrn, struct vmw_driver *vmw) +{ + ScreenPtr pScreen = pScrn->pScreen; + XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL; + XF86VideoAdaptorPtr newAdaptor = NULL; + int numAdaptors; + unsigned int ntot, nfree; + + debug_printf("%s: enter\n", __func__); + + if (vmw_ioctl_num_streams(vmw, &ntot, &nfree) != 0) { + debug_printf("No stream ioctl support\n"); + return FALSE; + } + + if (nfree == 0) { + debug_printf("No free streams\n"); + return FALSE; + } + + numAdaptors = xf86XVListGenericAdaptors(pScrn, &overlayAdaptors); + + newAdaptor = vmw_video_init_adaptor(pScrn, vmw); + if (!newAdaptor) { + debug_printf("Failed to initialize Xv extension\n"); + return FALSE; + } + + if (!numAdaptors) { + numAdaptors = 1; + overlayAdaptors = &newAdaptor; + } else { + newAdaptors = xalloc((numAdaptors + 1) * + sizeof(XF86VideoAdaptorPtr*)); + if (!newAdaptors) { + xf86XVFreeVideoAdaptorRec(newAdaptor); + return FALSE; + } + + memcpy(newAdaptors, overlayAdaptors, + numAdaptors * sizeof(XF86VideoAdaptorPtr)); + newAdaptors[numAdaptors++] = newAdaptor; + overlayAdaptors = newAdaptors; + } + + if (!xf86XVScreenInit(pScreen, overlayAdaptors, numAdaptors)) { + debug_printf("Failed to initialize Xv extension\n"); + xf86XVFreeVideoAdaptorRec(newAdaptor); + return FALSE; + } + + if (newAdaptors) { + xfree(newAdaptors); + } + + debug_printf("Initialized VMware Xv extension successfully\n"); + + return TRUE; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_close -- + * + * Unitializes video. + * + * Results: + * TRUE. + * + * Side effects: + * vmw->video_priv = NULL + * + *----------------------------------------------------------------------------- + */ + +Bool +vmw_video_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw) +{ + struct vmw_video_private *video; + int i; + + debug_printf("%s: enter\n", __func__); + + video = vmw->video_priv; + if (!video) + return TRUE; + + for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { + /* make sure the port is stoped as well */ + vmw_xv_stop_video(pScrn, &video->port[i], TRUE); + vmw_ioctl_unref_stream(vmw, video->port[i].streamId); + } + + /* XXX: I'm sure this function is missing code for turning off Xv */ + + free(vmw->video_priv); + vmw->video_priv = NULL; + + return TRUE; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_stop_all -- + * + * Stop all video streams from playing. + * + * Results: + * None. + * + * Side effects: + * All buffers are freed. + * + *----------------------------------------------------------------------------- + */ + +void vmw_video_stop_all(ScrnInfoPtr pScrn, struct vmw_driver *vmw) +{ + struct vmw_video_private *video = vmw->video_priv; + int i; + + debug_printf("%s: enter\n", __func__); + + if (!video) + return; + + for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { + vmw_xv_stop_video(pScrn, &video->port[i], TRUE); + } +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_init_adaptor -- + * + * Initializes a XF86VideoAdaptor structure with the capabilities and + * functions supported by this video driver. + * + * Results: + * On success initialized XF86VideoAdaptor struct or NULL on error + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static XF86VideoAdaptorPtr +vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_driver *vmw) +{ + XF86VideoAdaptorPtr adaptor; + struct vmw_video_private *video; + int i; + + debug_printf("%s: enter \n", __func__); + + adaptor = xf86XVAllocateVideoAdaptorRec(pScrn); + if (!adaptor) { + debug_printf("Not enough memory\n"); + return NULL; + } + + video = xcalloc(1, sizeof(*video)); + if (!video) { + debug_printf("Not enough memory.\n"); + xf86XVFreeVideoAdaptorRec(adaptor); + return NULL; + } + + vmw->video_priv = video; + + adaptor->type = XvInputMask | XvImageMask | XvWindowMask; + adaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adaptor->name = "VMware Video Engine"; + adaptor->nEncodings = VMWARE_VID_NUM_ENCODINGS; + adaptor->pEncodings = vmwareVideoEncodings; + adaptor->nFormats = VMWARE_VID_NUM_FORMATS; + adaptor->pFormats = vmwareVideoFormats; + adaptor->nPorts = VMWARE_VID_NUM_PORTS; + adaptor->pPortPrivates = video->port_ptr; + + for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { + vmw_ioctl_claim_stream(vmw, &video->port[i].streamId); + video->port[i].play = vmw_video_port_init; + video->port[i].flags = SVGA_VIDEO_FLAG_COLORKEY; + video->port[i].colorKey = VMWARE_VIDEO_COLORKEY; + video->port[i].isAutoPaintColorkey = TRUE; + adaptor->pPortPrivates[i].ptr = &video->port[i]; + } + + adaptor->nAttributes = VMWARE_VID_NUM_ATTRIBUTES; + adaptor->pAttributes = vmwareVideoAttributes; + + adaptor->nImages = VMWARE_VID_NUM_IMAGES; + adaptor->pImages = vmwareVideoImages; + + adaptor->PutVideo = NULL; + adaptor->PutStill = NULL; + adaptor->GetVideo = NULL; + adaptor->GetStill = NULL; + adaptor->StopVideo = vmw_xv_stop_video; + adaptor->SetPortAttribute = vmw_xv_set_port_attribute; + adaptor->GetPortAttribute = vmw_xv_get_port_attribute; + adaptor->QueryBestSize = vmw_xv_query_best_size; + adaptor->PutImage = vmw_xv_put_image; + adaptor->QueryImageAttributes = vmw_xv_query_image_attributes; + + debug_printf("%s: done %p\n", __func__, adaptor); + + return adaptor; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_port_init -- + * + * Initializes a video stream in response to the first PutImage() on a + * video stream. The process goes as follows: + * - Figure out characteristics according to format + * - Allocate offscreen memory + * - Pass on video to Play() functions + * + * Results: + * Success or XvBadAlloc on failure. + * + * Side effects: + * Video stream is initialized and its first frame sent to the host + * (done by VideoPlay() function called at the end) + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_video_port_init(ScrnInfoPtr pScrn, struct vmw_video_port *port, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes) +{ + struct vmw_driver *vmw = vmw_driver(pScrn); + unsigned short w, h; + int i, ret; + + debug_printf("\t%s: id %d, format %d\n", __func__, port->streamId, format); + + w = width; + h = height; + /* init all the format attributes, used for buffers */ + port->size = vmw_xv_query_image_attributes(pScrn, format, &w, &h, + port->pitches, port->offsets); + + if (port->size == -1) + return XvBadAlloc; + + port->play = vmw_video_port_play; + + for (i = 0; i < VMWARE_VID_NUM_BUFFERS; ++i) { + ret = vmw_video_buffer_alloc(vmw, port->size, &port->bufs[i]); + if (ret != Success) + break; + } + + /* Free all allocated buffers on failure */ + if (ret != Success) { + for (--i; i >= 0; --i) { + vmw_video_buffer_free(vmw, &port->bufs[i]); + } + return ret; + } + + port->currBuf = 0; + + REGION_COPY(pScrn->pScreen, &port->clipBoxes, clipBoxes); + + if (port->isAutoPaintColorkey) + xf86XVFillKeyHelper(pScrn->pScreen, port->colorKey, clipBoxes); + + return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, + drw_w, drw_h, format, buf, width, height, clipBoxes); +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_port_play -- + * + * Sends all the attributes associated with the video frame using the + * FIFO ESCAPE mechanism to the host. + * + * Results: + * Always returns Success. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes) +{ + struct vmw_driver *vmw = vmw_driver(pScrn); + struct drm_vmw_control_stream_arg arg; + unsigned short w, h; + int size; + int ret; + + debug_printf("\t%s: enter\n", __func__); + + w = width; + h = height; + + /* we don't update the ports size */ + size = vmw_xv_query_image_attributes(pScrn, format, &w, &h, + port->pitches, port->offsets); + + if (size > port->size) { + debug_printf("\t%s: Increase in size of Xv video frame streamId:%d.\n", + __func__, port->streamId); + vmw_xv_stop_video(pScrn, port, TRUE); + return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, + src_h, drw_w, drw_h, format, buf, width, height, + clipBoxes); + } + + memcpy(port->bufs[port->currBuf].data, buf, port->size); + + memset(&arg, 0, sizeof(arg)); + + arg.stream_id = port->streamId; + arg.enabled = TRUE; + arg.flags = port->flags; + arg.color_key = port->colorKey; + arg.handle = port->bufs[port->currBuf].handle; + arg.format = format; + arg.size = port->size; + arg.width = w; + arg.height = h; + arg.src.x = src_x; + arg.src.y = src_y; + arg.src.w = src_w; + arg.src.h = src_h; + arg.dst.x = drw_x; + arg.dst.y = drw_y; + arg.dst.w = drw_w; + arg.dst.h = drw_h; + arg.pitch[0] = port->pitches[0]; + arg.pitch[1] = port->pitches[1]; + arg.pitch[2] = port->pitches[2]; + arg.offset = 0; + + /* + * Update the clipList and paint the colorkey, if required. + */ + if (!REGION_EQUAL(pScrn->pScreen, &port->clipBoxes, clipBoxes)) { + REGION_COPY(pScrn->pScreen, &port->clipBoxes, clipBoxes); + if (port->isAutoPaintColorkey) { + xf86XVFillKeyHelper(pScrn->pScreen, port->colorKey, clipBoxes); + } + } + + ret = drmCommandWrite(vmw->fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg)); + if (ret) { + vmw_video_port_cleanup(pScrn, port); + return XvBadAlloc; + } + + port->currBuf = ++port->currBuf & (VMWARE_VID_NUM_BUFFERS - 1); + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_port_cleanup -- + * + * Frees up all resources (if any) taken by a video stream. + * + * Results: + * None. + * + * Side effects: + * Same as above. + * + *----------------------------------------------------------------------------- + */ + +static void +vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmw_video_port *port) +{ + struct vmw_driver *vmw = vmw_driver(pScrn); + uint32 id, colorKey, flags; + Bool isAutoPaintColorkey; + int i; + + debug_printf("\t%s: enter\n", __func__); + + for (i = 0; i < VMWARE_VID_NUM_BUFFERS; i++) { + vmw_video_buffer_free(vmw, &port->bufs[i]); + } + + /* + * reset stream for next video + */ + id = port->streamId; + colorKey = port->colorKey; + flags = port->flags; + isAutoPaintColorkey = port->isAutoPaintColorkey; + + memset(port, 0, sizeof(*port)); + + port->streamId = id; + port->play = vmw_video_port_init; + port->colorKey = colorKey; + port->flags = flags; + port->isAutoPaintColorkey = isAutoPaintColorkey; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_buffer_alloc -- + * + * Allocates and map a kernel buffer to be used as data storage. + * + * Results: + * XvBadAlloc on failure, otherwise Success. + * + * Side effects: + * Calls into the kernel, sets members of out. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_video_buffer_alloc(struct vmw_driver *vmw, int size, + struct vmw_video_buffer *out) +{ + out->buf = vmw_ioctl_buffer_create(vmw, size, &out->handle); + if (!out->buf) + return XvBadAlloc; + + out->data = vmw_ioctl_buffer_map(vmw, out->buf); + if (!out->data) { + vmw_ioctl_buffer_destroy(vmw, out->buf); + + out->handle = 0; + out->buf = NULL; + + return XvBadAlloc; + } + + out->size = size; + out->extra_data = xcalloc(1, size); + + debug_printf("\t\t%s: allocated buffer %p of size %i\n", __func__, out, size); + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_buffer_free -- + * + * Frees and unmaps an allocated kernel buffer. + * + * Results: + * Success. + * + * Side effects: + * Calls into the kernel, sets members of out to 0. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_video_buffer_free(struct vmw_driver *vmw, + struct vmw_video_buffer *out) +{ + if (out->size == 0) + return Success; + + xfree(out->extra_data); + vmw_ioctl_buffer_unmap(vmw, out->buf); + vmw_ioctl_buffer_destroy(vmw, out->buf); + + out->buf = NULL; + out->data = NULL; + out->handle = 0; + out->size = 0; + + debug_printf("\t\t%s: freed buffer %p\n", __func__, out); + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_put_image -- + * + * Main video playback function. It copies the passed data which is in + * the specified format (e.g. FOURCC_YV12) into the overlay. + * + * If sync is TRUE the driver should not return from this + * function until it is through reading the data from buf. + * + * Results: + * Success or XvBadAlloc on failure + * + * Side effects: + * Video port will be played(initialized if 1st frame) on success + * or will fail on error. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, + short drw_x, short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, short height, + Bool sync, RegionPtr clipBoxes, pointer data, + DrawablePtr dst) +{ + struct vmw_driver *vmw = vmw_driver(pScrn); + struct vmw_video_port *port = data; + + debug_printf("%s: enter (%u, %u) (%ux%u) (%u, %u) (%ux%u) (%ux%u)\n", __func__, + src_x, src_y, src_w, src_h, + drw_x, drw_y, drw_w, drw_h, + width, height); + + if (!vmw->video_priv) + return XvBadAlloc; + + return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, + drw_w, drw_h, format, buf, width, height, clipBoxes); +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_stop_video -- + * + * Called when we should stop playing video for a particular stream. If + * Cleanup is FALSE, the "stop" operation is only temporary, and thus we + * don't do anything. If Cleanup is TRUE we kill the video port by + * sending a message to the host and freeing up the stream. + * + * Results: + * None. + * + * Side effects: + * See above. + * + *----------------------------------------------------------------------------- + */ + +static void +vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup) +{ + struct vmw_driver *vmw = vmw_driver(pScrn); + struct vmw_video_port *port = data; + struct drm_vmw_control_stream_arg arg; + int ret; + + debug_printf("%s: cleanup is %s\n", __func__, cleanup ? "TRUE" : "FALSE"); + + if (!vmw->video_priv) + return; + + if (!cleanup) + return; + + + memset(&arg, 0, sizeof(arg)); + arg.stream_id = port->streamId; + arg.enabled = FALSE; + + ret = drmCommandWrite(vmw->fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg)); + assert(ret == 0); + + vmw_video_port_cleanup(pScrn, port); +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_query_image_attributes -- + * + * From the spec: This function is called to let the driver specify how data + * for a particular image of size width by height should be stored. + * Sometimes only the size and corrected width and height are needed. In + * that case pitches and offsets are NULL. + * + * Results: + * The size of the memory required for the image, or -1 on error. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format, + unsigned short *width, unsigned short *height, + int *pitches, int *offsets) +{ + INT32 size, tmp; + + if (*width > VMWARE_VID_MAX_WIDTH) { + *width = VMWARE_VID_MAX_WIDTH; + } + if (*height > VMWARE_VID_MAX_HEIGHT) { + *height = VMWARE_VID_MAX_HEIGHT; + } + + *width = (*width + 1) & ~1; + if (offsets != NULL) { + offsets[0] = 0; + } + + switch (format) { + case FOURCC_YV12: + *height = (*height + 1) & ~1; + size = (*width + 3) & ~3; + if (pitches) { + pitches[0] = size; + } + size *= *height; + if (offsets) { + offsets[1] = size; + } + tmp = ((*width >> 1) + 3) & ~3; + if (pitches) { + pitches[1] = pitches[2] = tmp; + } + tmp *= (*height >> 1); + size += tmp; + if (offsets) { + offsets[2] = size; + } + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + size = *width * 2; + if (pitches) { + pitches[0] = size; + } + size *= *height; + break; + default: + debug_printf("Query for invalid video format %d\n", format); + return -1; + } + return size; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_set_port_attribute -- + * + * From the spec: A port may have particular attributes such as colorKey, hue, + * saturation, brightness or contrast. Xv clients set these + * attribute values by sending attribute strings (Atoms) to the server. + * + * Results: + * Success if the attribute exists and XvBadAlloc otherwise. + * + * Side effects: + * The respective attribute gets the new value. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, pointer data) +{ + struct vmw_video_port *port = data; + Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); + Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + + if (attribute == xvColorKey) { + debug_printf("%s: Set colorkey:0x%x\n", __func__, (unsigned)value); + port->colorKey = value; + } else if (attribute == xvAutoPaint) { + debug_printf("%s: Set autoPaint: %s\n", __func__, value? "TRUE": "FALSE"); + port->isAutoPaintColorkey = value; + } else { + return XvBadAlloc; + } + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_get_port_attribute -- + * + * From the spec: A port may have particular attributes such as hue, + * saturation, brightness or contrast. Xv clients get these + * attribute values by sending attribute strings (Atoms) to the server + * + * Results: + * Success if the attribute exists and XvBadAlloc otherwise. + * + * Side effects: + * "value" contains the requested attribute on success. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 *value, pointer data) +{ + struct vmw_video_port *port = data; + Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); + Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + + if (attribute == xvColorKey) { + *value = port->colorKey; + } else if (attribute == xvAutoPaint) { + *value = port->isAutoPaintColorkey; + } else { + return XvBadAlloc; + } + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_query_best_size -- + * + * From the spec: QueryBestSize provides the client with a way to query what + * the destination dimensions would end up being if they were to request + * that an area vid_w by vid_h from the video stream be scaled to rectangle + * of drw_w by drw_h on the screen. Since it is not expected that all + * hardware will be able to get the target dimensions exactly, it is + * important that the driver provide this function. + * + * This function seems to never be called, but to be on the safe side + * we apply the same logic that QueryImageAttributes has for width + * and height. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static void +vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, + short vid_w, short vid_h, short drw_w, + short drw_h, unsigned int *p_w, + unsigned int *p_h, pointer data) +{ + *p_w = (drw_w + 1) & ~1; + *p_h = drw_h; + + return; +} diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_xorg.c b/src/gallium/winsys/drm/vmware/xorg/vmw_xorg.c new file mode 100644 index 00000000000..4b208719ca3 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_xorg.c @@ -0,0 +1,152 @@ +/********************************************************** + * Copyright 2008-2009 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + * + **********************************************************/ + +/** + * @file + * Glue file for Xorg State Tracker. + * + * @author Alan Hourihane <[email protected]> + * @author Jakob Bornecrantz <[email protected]> + */ + +#include "vmw_hook.h" + +static void vmw_xorg_identify(int flags); +static Bool vmw_xorg_pci_probe(DriverPtr driver, + int entity_num, + struct pci_device *device, + intptr_t match_data); + +static const struct pci_id_match vmw_xorg_device_match[] = { + {0x15ad, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, +}; + +static SymTabRec vmw_xorg_chipsets[] = { + {PCI_MATCH_ANY, "VMware SVGA Device"}, + {-1, NULL} +}; + +static PciChipsets vmw_xorg_pci_devices[] = { + {PCI_MATCH_ANY, PCI_MATCH_ANY, NULL}, + {-1, -1, NULL} +}; + +static XF86ModuleVersionInfo vmw_xorg_version = { + "vmwgfx", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 0, 1, 0, /* major, minor, patch */ + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0, 0, 0, 0} +}; + +/* + * Xorg driver exported structures + */ + +_X_EXPORT DriverRec vmwgfx = { + 1, + "vmwgfx", + vmw_xorg_identify, + NULL, + xorg_tracker_available_options, + NULL, + 0, + NULL, + vmw_xorg_device_match, + vmw_xorg_pci_probe +}; + +static MODULESETUPPROTO(vmw_xorg_setup); + +_X_EXPORT XF86ModuleData vmwgfxModuleData = { + &vmw_xorg_version, + vmw_xorg_setup, + NULL +}; + +/* + * Xorg driver functions + */ + +static pointer +vmw_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = 0; + + /* This module should be loaded only once, but check to be sure. + */ + if (!setupDone) { + setupDone = 1; + xf86AddDriver(&vmwgfx, module, HaveDriverFuncs); + + /* + * The return value must be non-NULL on success even though there + * is no TearDownProc. + */ + return (pointer) 1; + } else { + if (errmaj) + *errmaj = LDR_ONCEONLY; + return NULL; + } +} + +static void +vmw_xorg_identify(int flags) +{ + xf86PrintChipsets("vmwgfx", "Driver for VMware SVGA device", + vmw_xorg_chipsets); +} + +static Bool +vmw_xorg_pci_probe(DriverPtr driver, + int entity_num, struct pci_device *device, intptr_t match_data) +{ + ScrnInfoPtr scrn = NULL; + EntityInfoPtr entity; + + scrn = xf86ConfigPciEntity(scrn, 0, entity_num, vmw_xorg_pci_devices, + NULL, NULL, NULL, NULL, NULL); + if (scrn != NULL) { + scrn->driverVersion = 1; + scrn->driverName = "vmwgfx"; + scrn->name = "vmwgfx"; + scrn->Probe = NULL; + + entity = xf86GetEntityInfo(entity_num); + + /* Use all the functions from the xorg tracker */ + xorg_tracker_set_functions(scrn); + + vmw_screen_set_functions(scrn); + } + return scrn != NULL; +} |