diff options
author | Younes Manton <[email protected]> | 2010-03-07 12:47:45 -0500 |
---|---|---|
committer | Younes Manton <[email protected]> | 2010-03-12 01:37:49 -0500 |
commit | a8238bb08a95e7ea4430450c304a6bee210df1a6 (patch) | |
tree | 00f4e852473dc1d6a86aece436f3e5bf89d029c7 /src/gallium/winsys/drm | |
parent | 80468464897682b8e10aeab310f20fdd7ddc6cb4 (diff) | |
parent | 45df4bad9fc0379f05197bee10c03fd351f24094 (diff) |
Merge remote branch 'origin/master' into pipe-video
Conflicts:
configure.ac
src/gallium/auxiliary/vl/Makefile
src/gallium/auxiliary/vl/SConscript
src/gallium/auxiliary/vl/vl_compositor.c
src/gallium/auxiliary/vl/vl_compositor.h
src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c
src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h
src/gallium/drivers/nouveau/nouveau_winsys.h
src/gallium/drivers/softpipe/sp_video_context.c
src/gallium/include/pipe/p_video_state.h
src/gallium/include/state_tracker/drm_api.h
src/gallium/state_trackers/xorg/xvmc/surface.c
src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c
src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h
src/gallium/winsys/drm/radeon/core/radeon_drm.c
src/gallium/winsys/g3dvl/nouveau/Makefile
Diffstat (limited to 'src/gallium/winsys/drm')
78 files changed, 2749 insertions, 771 deletions
diff --git a/src/gallium/winsys/drm/Makefile.egl b/src/gallium/winsys/drm/Makefile.egl new file mode 100644 index 00000000000..8363de6e975 --- /dev/null +++ b/src/gallium/winsys/drm/Makefile.egl @@ -0,0 +1,61 @@ +# src/gallium/winsys/drm/Makefile.egl + +# The driver Makefile should define +# +# EGL_DRIVER_NAME, the name of the driver +# EGL_DRIVER_SOURCES, the sources of the driver +# EGL_DRIVER_LIBS, extra libraries needed by the driver +# EGL_DRIVER_PIPES, the pipe drivers of the driver +# +# before including this file. + +EGL_DRIVER_OBJECTS = $(EGL_DRIVER_SOURCES:.c=.o) + +common_LIBS = -ldrm -lm -ldl + +x11_ST = $(TOP)/src/gallium/state_trackers/egl/libeglx11.a +x11_LIBS = $(common_LIBS) -lX11 -lXext -lXfixes + +kms_ST = $(TOP)/src/gallium/state_trackers/egl/libeglkms.a +kms_LIBS = $(common_LIBS) + +##### RULES ##### + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + + +##### TARGETS ##### + +EGL_DISPLAY_DRIVERS = $(foreach dpy, $(EGL_DISPLAYS), egl_$(dpy)_$(EGL_DRIVER_NAME).so) + +EGL_DISPLAY_LIBS = $(foreach drv, $(EGL_DISPLAY_DRIVERS), $(TOP)/$(LIB_DIR)/$(drv)) + +default: $(EGL_DISPLAY_LIBS) + +$(EGL_DISPLAY_LIBS): $(TOP)/$(LIB_DIR)/%.so: %.so + $(INSTALL) $< $(TOP)/$(LIB_DIR) + +define mklib-egl +$(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ + $(MKLIB_OPTIONS) $(EGL_DRIVER_OBJECTS) $($(1)_ST) \ + $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) $($(1)_LIBS) $(EGL_DRIVER_LIBS) +endef + +egl_x11_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(x11_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile + $(call mklib-egl,x11) + +egl_kms_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(kms_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile + $(call mklib-egl,kms) + +clean: + -rm -f $(EGL_DRIVER_OBJECTS) + -rm -f $(EGL_DISPLAY_DRIVERS) + +install: $(EGL_DISPLAY_LIBS) + $(INSTALL) -d $(DESTDIR)$(EGL_DRIVER_INSTALL_DIR) + for lib in $(EGL_DISPLAY_LIBS); do \ + $(MINSTALL) -m 755 "$$lib" $(DESTDIR)$(EGL_DRIVER_INSTALL_DIR); \ + done + +depend: diff --git a/src/gallium/winsys/drm/Makefile.template b/src/gallium/winsys/drm/Makefile.template index 9635c3c50e9..f4cc0def471 100644 --- a/src/gallium/winsys/drm/Makefile.template +++ b/src/gallium/winsys/drm/Makefile.template @@ -19,30 +19,12 @@ COMMON_BM_SOURCES = \ $(TOP)/src/mesa/drivers/dri/common/dri_bufmgr.c \ $(TOP)/src/mesa/drivers/dri/common/dri_drmpool.c - -ifeq ($(WINDOW_SYSTEM),dri) -WINOBJ= -WINLIB= INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES) OBJECTS = \ $(C_SOURCES:.c=.o) \ $(ASM_SOURCES:.S=.o) -else -# miniglx -WINOBJ= -WINLIB=-L$(MESA)/src/glx/mini -MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini -INCLUDES = $(MINIGLX_INCLUDES) \ - $(SHARED_INCLUDES) \ - $(PCIACCESS_CFLAGS) - -OBJECTS = $(C_SOURCES:.c=.o) \ - $(MINIGLX_SOURCES:.c=.o) \ - $(ASM_SOURCES:.S=.o) -endif - ### Include directories SHARED_INCLUDES = \ @@ -74,25 +56,19 @@ SHARED_INCLUDES = \ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ .S.o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ + $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ ##### TARGETS ##### default: depend symlinks $(TOP)/$(LIB_DIR)/gallium/$(LIBNAME) -$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template - $(MKLIB) -noprefix -o $@ \ +$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) Makefile \ + $(TOP)/src/mesa/drivers/dri/Makefile.template + $(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ $(OBJECTS) $(PIPE_DRIVERS) \ -Wl,--start-group $(MESA_MODULES) -Wl,--end-group \ - $(WINOBJ) $(DRI_LIB_DEPS) $(DRIVER_EXTRAS) - -$(LIBNAME_EGL): $(WINSYS_OBJECTS) $(LIBS) - $(MKLIB) -o $(LIBNAME_EGL) \ - -linker "$(CC)" \ - -noprefix \ - $(OBJECTS) $(MKLIB_OPTIONS) $(WINSYS_OBJECTS) $(PIPE_DRIVERS) $(WINOBJ) $(DRI_LIB_DEPS) \ - --whole-archive $(LIBS) $(GALLIUM_AUXILIARIES) --no-whole-archive $(DRIVER_EXTRAS) + $(DRI_LIB_DEPS) $(DRIVER_EXTRAS) $(TOP)/$(LIB_DIR)/gallium: mkdir -p $@ diff --git a/src/gallium/winsys/drm/SConscript b/src/gallium/winsys/drm/SConscript index 9f7b383d2d3..66b73a8bf93 100644 --- a/src/gallium/winsys/drm/SConscript +++ b/src/gallium/winsys/drm/SConscript @@ -58,6 +58,11 @@ if env['dri']: '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..1c132582005 --- /dev/null +++ b/src/gallium/winsys/drm/i965/egl/Makefile @@ -0,0 +1,14 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +EGL_DRIVER_NAME = i965 +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -ldrm_intel + +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/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 + +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/i965/egl/dummy.c b/src/gallium/winsys/drm/i965/egl/dummy.c new file mode 100644 index 00000000000..3181d0ba7e8 --- /dev/null +++ b/src/gallium/winsys/drm/i965/egl/dummy.c @@ -0,0 +1,3 @@ +/* A poor man's --whole-archive for EGL drivers */ +void *_eglMain(void *); +void *_eglWholeArchive = (void *) _eglMain; 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..a061eef0beb --- /dev/null +++ b/src/gallium/winsys/drm/i965/gem/i965_drm_api.c @@ -0,0 +1,238 @@ + +#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 void +destroy(struct drm_api *api) +{ + if (BRW_DUMP) + debug_printf("%s\n", __FUNCTION__); + +} + +struct drm_api i965_libdrm_api = +{ + .name = "i965", + .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..07be1df87f0 --- /dev/null +++ b/src/gallium/winsys/drm/i965/gem/i965_drm_buffer.c @@ -0,0 +1,428 @@ + +#include "i965_drm_winsys.h" +#include "util/u_memory.h" +#include "util/u_inlines.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..74501eeb16f --- /dev/null +++ b/src/gallium/winsys/drm/i965/xlib/xlib_i965.c @@ -0,0 +1,503 @@ +/************************************************************************** + * + * 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; +} + + + + + +struct xm_driver xlib_i965_driver = +{ + .create_pipe_screen = xlib_create_i965_screen, + .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..c25726b0bb1 --- /dev/null +++ b/src/gallium/winsys/drm/i965/xorg/Makefile @@ -0,0 +1,54 @@ +TOP = ../../../../../.. + + +GALLIUMDIR = $(TOP)/src/gallium + +TARGET = i965g_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) \ + -I${GALLIUMDIR}/include \ + -I${GALLIUMDIR}/drivers \ + -I${GALLIUMDIR}/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) + +TARGET_STAGING = $(TOP)/$(LIB_DIR)/gallium/$(TARGET) +############################################# + +all default: $(TARGET) $(TARGET_STAGING) + +$(TARGET): $(OBJECTS) Makefile $(GALLIUMDIR)/state_trackers/xorg/libxorgtracker.a $(LIBS) + $(TOP)/bin/mklib -noprefix -o $@ \ + $(OBJECTS) $(LIBS) $(shell pkg-config --libs libdrm) -ldrm_intel + +$(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) + +.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..0df841d8798 100644 --- a/src/gallium/winsys/drm/intel/dri/SConscript +++ b/src/gallium/winsys/drm/intel/dri/SConscript @@ -4,17 +4,18 @@ env = drienv.Clone() env.ParseConfig('pkg-config --cflags --libs libdrm_intel') -drivers = [ +env.Prepend(LIBS = [ st_dri, inteldrm, - softpipe, i915, trace, -] + mesa, + glsl, + gallium +]) env.LoadableModule( target ='i915_dri.so', source = COMMON_GALLIUM_SOURCES, - LIBS = drivers + mesa + auxiliaries + env['LIBS'], SHLIBPREFIX = '', ) diff --git a/src/gallium/winsys/drm/intel/egl/Makefile b/src/gallium/winsys/drm/intel/egl/Makefile index 1397e9f7290..60d675ca73d 100644 --- a/src/gallium/winsys/drm/intel/egl/Makefile +++ b/src/gallium/winsys/drm/intel/egl/Makefile @@ -1,29 +1,14 @@ TOP = ../../../../../.. -GALLIUMDIR = ../../../.. include $(TOP)/configs/current -LIBNAME = EGL_i915.so +EGL_DRIVER_NAME = i915 +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -ldrm_intel -PIPE_DRIVERS = \ - $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ - $(GALLIUMDIR)/winsys/drm/intel/gem/libinteldrm.a \ +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/i915/libi915.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: +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/intel/egl/dummy.c b/src/gallium/winsys/drm/intel/egl/dummy.c new file mode 100644 index 00000000000..3181d0ba7e8 --- /dev/null +++ b/src/gallium/winsys/drm/intel/egl/dummy.c @@ -0,0 +1,3 @@ +/* A poor man's --whole-archive for EGL drivers */ +void *_eglMain(void *); +void *_eglWholeArchive = (void *) _eglMain; 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..377ed255131 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_drm_api.c +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c @@ -1,3 +1,4 @@ +#include <stdio.h> #include "state_tracker/drm_api.h" @@ -32,6 +33,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); } @@ -174,18 +176,11 @@ intel_drm_create_screen(struct drm_api *api, int drmFD, idws->pools.gem = drm_intel_bufmgr_gem_init(idws->fd, idws->max_batch_size); drm_intel_bufmgr_gem_enable_reuse(idws->pools.gem); - idws->softpipe = FALSE; idws->dump_cmd = debug_get_bool_option("INTEL_DUMP_CMD", FALSE); return i915_create_screen(&idws->base, deviceID); } -static struct pipe_context * -intel_drm_create_context(struct drm_api *api, struct pipe_screen *screen) -{ - return i915_create_context(screen); -} - static void destroy(struct drm_api *api) { @@ -194,7 +189,8 @@ destroy(struct drm_api *api) struct drm_api intel_drm_api = { - .create_context = intel_drm_create_context, + .name = "i915", + .driver_name = "i915", .create_screen = intel_drm_create_screen, .texture_from_shared_handle = intel_drm_texture_from_shared_handle, .shared_handle_from_texture = intel_drm_shared_handle_from_texture, 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..102faedfeae 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c @@ -1,7 +1,8 @@ #include "intel_drm_winsys.h" #include "util/u_memory.h" -#include "pipe/p_refcnt.h" +#include "util/u_atomic.h" +#include "util/u_inlines.h" /** * Because gem does not have fence's we have to create our own fences. @@ -39,11 +40,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/intel/gem/intel_drm_winsys.h b/src/gallium/winsys/drm/intel/gem/intel_drm_winsys.h index b4a60563ef4..9786ee93650 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_drm_winsys.h +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_winsys.h @@ -17,7 +17,6 @@ struct intel_drm_winsys { struct intel_winsys base; - boolean softpipe; boolean dump_cmd; int fd; /**< Drm file discriptor */ diff --git a/src/gallium/winsys/drm/nouveau/dri/Makefile b/src/gallium/winsys/drm/nouveau/dri/Makefile index 61abc439d31..c7f758d9d9c 100644 --- a/src/gallium/winsys/drm/nouveau/dri/Makefile +++ b/src/gallium/winsys/drm/nouveau/dri/Makefile @@ -6,9 +6,6 @@ LIBNAME = nouveau_dri.so PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ - $(TOP)/src/gallium/drivers/nv04/libnv04.a \ - $(TOP)/src/gallium/drivers/nv10/libnv10.a \ - $(TOP)/src/gallium/drivers/nv20/libnv20.a \ $(TOP)/src/gallium/drivers/nv30/libnv30.a \ $(TOP)/src/gallium/drivers/nv40/libnv40.a \ $(TOP)/src/gallium/drivers/nv50/libnv50.a \ 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 d467305d4c0..d289fdcec7f 100644 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c @@ -1,6 +1,8 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "util/u_format.h" #include "util/u_memory.h" +#include "util/u_inlines.h" #include "nouveau_drm_api.h" @@ -53,6 +55,15 @@ static struct dri1_api nouveau_dri1_api = { nouveau_dri1_front_surface, }; +static void +nouveau_drm_destroy_winsys(struct pipe_winsys *s) +{ + struct nouveau_winsys *nv_winsys = nouveau_winsys(s); + struct nouveau_screen *nv_screen= nouveau_screen(nv_winsys->pscreen); + nouveau_device_close(&nv_screen->device); + FREE(nv_winsys); +} + static struct pipe_screen * nouveau_drm_create_screen(struct drm_api *api, int fd, struct drm_create_screen_arg *arg) @@ -70,15 +81,6 @@ nouveau_drm_create_screen(struct drm_api *api, int fd, return NULL; switch (dev->chipset & 0xf0) { - case 0x00: - init = nv04_screen_create; - break; - case 0x10: - init = nv10_screen_create; - break; - case 0x20: - init = nv20_screen_create; - break; case 0x30: init = nv30_screen_create; break; @@ -86,6 +88,7 @@ nouveau_drm_create_screen(struct drm_api *api, int fd, case 0x60: init = nv40_screen_create; break; + case 0x50: case 0x80: case 0x90: case 0xa0: @@ -103,6 +106,7 @@ nouveau_drm_create_screen(struct drm_api *api, int fd, return NULL; } ws = &nvws->base; + ws->destroy = nouveau_drm_destroy_winsys; nvws->pscreen = init(ws, dev); if (!nvws->pscreen) { @@ -115,9 +119,9 @@ nouveau_drm_create_screen(struct drm_api *api, int fd, enum pipe_format format; if (nvdri->bpp == 16) - format = PIPE_FORMAT_R5G6B5_UNORM; + format = PIPE_FORMAT_B5G6R5_UNORM; else - format = PIPE_FORMAT_A8R8G8B8_UNORM; + format = PIPE_FORMAT_B8G8R8A8_UNORM; nvws->front = dri_surface_from_handle(api, nvws->pscreen, nvdri->front_offset, @@ -138,105 +142,6 @@ nouveau_drm_create_screen(struct drm_api *api, int fd, return nvws->pscreen; } -static struct pipe_context * -nouveau_drm_create_context(struct drm_api *api, struct pipe_screen *pscreen) -{ - struct nouveau_winsys *nvws = nouveau_winsys_screen(pscreen); - struct pipe_context *(*init)(struct pipe_screen *, unsigned); - unsigned chipset = nouveau_screen(pscreen)->device->chipset; - int i; - - switch (chipset & 0xf0) { - case 0x00: - init = nv04_create; - break; - case 0x10: - init = nv10_create; - break; - case 0x20: - init = nv20_create; - break; - case 0x30: - init = nv30_create; - break; - case 0x40: - case 0x60: - init = nv40_create; - break; - case 0x80: - case 0x90: - case 0xa0: - init = nv50_create; - break; - default: - debug_printf("%s: unknown chipset nv%02x\n", __func__, chipset); - return NULL; - } - - /* Find a free slot for a pipe context, allocate a new one if needed */ - for (i = 0; i < nvws->nr_pctx; i++) { - if (nvws->pctx[i] == NULL) - break; - } - - if (i == nvws->nr_pctx) { - nvws->nr_pctx++; - nvws->pctx = realloc(nvws->pctx, - sizeof(*nvws->pctx) * nvws->nr_pctx); - } - - nvws->pctx[i] = init(pscreen, i); - return nvws->pctx[i]; -} - -typedef struct pipe_video_context* (*nouveau_video_create)(struct pipe_context *pipe, - enum pipe_video_profile profile, - enum pipe_video_chroma_format chroma_format, - unsigned width, unsigned height, - unsigned pvctx); - -static struct pipe_video_context * -nouveau_drm_create_video_context(struct drm_api *api, struct pipe_screen *pscreen, - enum pipe_video_profile profile, - enum pipe_video_chroma_format chroma_format, - unsigned width, unsigned height) -{ - struct nouveau_winsys *nvws = nouveau_winsys_screen(pscreen); - nouveau_video_create init; - unsigned chipset = nouveau_screen(pscreen)->device->chipset; - struct pipe_context *pipe; - int i; - - switch (chipset & 0xf0) { - case 0x40: - case 0x60: - init = nv40_video_create; - break; - default: - debug_printf("%s: unknown chipset nv%02x\n", __func__, chipset); - return NULL; - } - - /* Find a free slot for a pipe video context, allocate a new one if needed */ - for (i = 0; i < nvws->nr_pvctx; i++) { - if (nvws->pvctx[i] == NULL) - break; - } - - if (i == nvws->nr_pvctx) { - nvws->nr_pvctx++; - nvws->pvctx = realloc(nvws->pvctx, - sizeof(*nvws->pvctx) * nvws->nr_pvctx); - } - - pipe = nouveau_drm_create_context(api, pscreen); - if (!pipe) - return NULL; - - nvws->pvctx[i] = init(pipe, profile, chroma_format, width, height, i); - return nvws->pvctx[i]; -} - static struct pipe_texture * nouveau_drm_pt_from_name(struct drm_api *api, struct pipe_screen *pscreen, struct pipe_texture *templ, const char *name, @@ -294,14 +199,14 @@ nouveau_drm_handle_from_pt(struct drm_api *api, struct pipe_screen *pscreen, return false; *handle = mt->bo->handle; - *stride = pf_get_stride(mt->base.format, mt->base.width0); + *stride = util_format_get_stride(mt->base.format, mt->base.width0); return true; } struct drm_api drm_api_hooks = { + .name = "nouveau", + .driver_name = "nouveau", .create_screen = nouveau_drm_create_screen, - .create_context = nouveau_drm_create_context, - .create_video_context = nouveau_drm_create_video_context, .texture_from_shared_handle = nouveau_drm_pt_from_name, .shared_handle_from_texture = nouveau_drm_name_from_pt, .local_handle_from_texture = nouveau_drm_handle_from_pt, diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h index fa4e821e60c..a91aad7df8e 100644 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h @@ -4,7 +4,7 @@ #include "state_tracker/drm_api.h" #include "state_tracker/dri1_api.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" #include "nouveau_dri.h" @@ -13,11 +13,6 @@ struct nouveau_winsys { struct pipe_screen *pscreen; - unsigned nr_pctx; - struct pipe_context **pctx; - unsigned nr_pvctx; - struct pipe_video_context **pvctx; - struct pipe_surface *front; }; diff --git a/src/gallium/winsys/drm/nouveau/egl/Makefile b/src/gallium/winsys/drm/nouveau/egl/Makefile new file mode 100644 index 00000000000..2c352603320 --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/egl/Makefile @@ -0,0 +1,16 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +EGL_DRIVER_NAME = nouveau +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -ldrm_nouveau + +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ + $(TOP)/src/gallium/drivers/nv30/libnv30.a \ + $(TOP)/src/gallium/drivers/nv40/libnv40.a \ + $(TOP)/src/gallium/drivers/nv50/libnv50.a \ + $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a + +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/nouveau/egl/dummy.c b/src/gallium/winsys/drm/nouveau/egl/dummy.c new file mode 100644 index 00000000000..3181d0ba7e8 --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/egl/dummy.c @@ -0,0 +1,3 @@ +/* A poor man's --whole-archive for EGL drivers */ +void *_eglMain(void *); +void *_eglWholeArchive = (void *) _eglMain; diff --git a/src/gallium/winsys/drm/nouveau/xorg/Makefile b/src/gallium/winsys/drm/nouveau/xorg/Makefile index f0d3b337e83..179b50230b5 100644 --- a/src/gallium/winsys/drm/nouveau/xorg/Makefile +++ b/src/gallium/winsys/drm/nouveau/xorg/Makefile @@ -18,9 +18,6 @@ INCLUDES = \ LIBS = \ $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ - $(TOP)/src/gallium/drivers/nv04/libnv04.a \ - $(TOP)/src/gallium/drivers/nv10/libnv10.a \ - $(TOP)/src/gallium/drivers/nv20/libnv20.a \ $(TOP)/src/gallium/drivers/nv30/libnv30.a \ $(TOP)/src/gallium/drivers/nv40/libnv40.a \ $(TOP)/src/gallium/drivers/nv50/libnv50.a \ 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 2a8daed051d..e5c69199330 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c @@ -31,11 +31,13 @@ */ #include "radeon_buffer.h" +#include "radeon_drm.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 "util/u_memory.h" + +#include "radeon_bo_gem.h" #include <X11/Xutil.h> struct radeon_vl_context @@ -50,6 +52,26 @@ static const char *radeon_get_name(struct pipe_winsys *ws) return "Radeon/GEM+KMS"; } +static uint32_t radeon_domain_from_usage(unsigned usage) +{ + uint32_t domain = 0; + + if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) { + domain |= RADEON_GEM_DOMAIN_VRAM; + } + if (usage & PIPE_BUFFER_USAGE_PIXEL) { + domain |= RADEON_GEM_DOMAIN_VRAM; + } + if (usage & PIPE_BUFFER_USAGE_VERTEX) { + domain |= RADEON_GEM_DOMAIN_GTT; + } + if (usage & PIPE_BUFFER_USAGE_INDEX) { + domain |= RADEON_GEM_DOMAIN_GTT; + } + + return domain; +} + static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws, unsigned alignment, unsigned usage, @@ -57,6 +79,7 @@ static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws, { struct radeon_winsys *radeon_ws = (struct radeon_winsys *)ws; struct radeon_pipe_buffer *radeon_buffer; + struct pb_desc desc; uint32_t domain; radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer); @@ -69,18 +92,16 @@ static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws, radeon_buffer->base.usage = usage; radeon_buffer->base.size = size; - domain = 0; - - if (usage & PIPE_BUFFER_USAGE_PIXEL) { - domain |= RADEON_GEM_DOMAIN_VRAM; - } - if (usage & PIPE_BUFFER_USAGE_VERTEX) { - domain |= RADEON_GEM_DOMAIN_GTT; - } - if (usage & PIPE_BUFFER_USAGE_INDEX) { - domain |= RADEON_GEM_DOMAIN_GTT; + if (usage & PIPE_BUFFER_USAGE_CONSTANT && is_r3xx(radeon_ws->pci_id)) { + /* Don't bother allocating a BO, as it'll never get to the card. */ + desc.alignment = alignment; + desc.usage = usage; + radeon_buffer->pb = pb_malloc_buffer_create(size, &desc); + return &radeon_buffer->base; } + domain = radeon_domain_from_usage(usage); + radeon_buffer->bo = radeon_bo_open(radeon_ws->priv->bom, 0, size, alignment, domain, 0); if (radeon_buffer->bo == NULL) { @@ -120,8 +141,8 @@ static struct pipe_buffer *radeon_surface_buffer_create(struct pipe_winsys *ws, const unsigned alignment = 64; unsigned nblocksy, size; - nblocksy = pf_get_nblocksy(format, height); - *stride = align(pf_get_stride(format, width), alignment); + 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); @@ -132,8 +153,16 @@ static void radeon_buffer_del(struct pipe_buffer *buffer) struct radeon_pipe_buffer *radeon_buffer = (struct radeon_pipe_buffer*)buffer; - radeon_bo_unref(radeon_buffer->bo); - free(radeon_buffer); + if (radeon_buffer->pb) { + pipe_reference_init(&radeon_buffer->pb->base.reference, 0); + pb_destroy(radeon_buffer->pb); + } + + if (radeon_buffer->bo) { + radeon_bo_unref(radeon_buffer->bo); + } + + FREE(radeon_buffer); } static void *radeon_buffer_map(struct pipe_winsys *ws, @@ -145,8 +174,8 @@ static void *radeon_buffer_map(struct pipe_winsys *ws, (struct radeon_pipe_buffer*)buffer; int write = 0; - if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) { - priv->cs->space_flush_fn(priv->cs->space_flush_data); + if (radeon_buffer->pb) { + return pb_map(radeon_buffer->pb, flags); } if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { @@ -155,6 +184,11 @@ static void *radeon_buffer_map(struct pipe_winsys *ws, if (radeon_bo_is_busy(radeon_buffer->bo, &domain)) return NULL; } + + if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) { + priv->flush_cb(priv->flush_data); + } + if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) { write = 1; } @@ -172,7 +206,42 @@ static void radeon_buffer_unmap(struct pipe_winsys *ws, struct radeon_pipe_buffer *radeon_buffer = (struct radeon_pipe_buffer*)buffer; - radeon_bo_unmap(radeon_buffer->bo); + if (radeon_buffer->pb) { + pb_unmap(radeon_buffer->pb); + } else { + radeon_bo_unmap(radeon_buffer->bo); + } +} + +static void radeon_buffer_set_tiling(struct radeon_winsys *ws, + struct pipe_buffer *buffer, + uint32_t pitch, + boolean microtiled, + boolean macrotiled) +{ + struct radeon_winsys_priv *priv = ((struct radeon_winsys *)ws)->priv; + struct radeon_pipe_buffer *radeon_buffer = + (struct radeon_pipe_buffer*)buffer; + uint32_t flags = 0, old_flags, old_pitch; + + if (microtiled) { + flags |= RADEON_BO_FLAGS_MICRO_TILE; + } + if (macrotiled) { + flags |= RADEON_BO_FLAGS_MACRO_TILE; + } + + radeon_bo_get_tiling(radeon_buffer->bo, &old_flags, &old_pitch); + + if (flags != old_flags || pitch != old_pitch) { + /* Tiling determines how DRM treats the buffer data. + * We must flush CS when changing it if the buffer is referenced. */ + if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) { + priv->flush_cb(priv->flush_data); + } + + radeon_bo_set_tiling(radeon_buffer->bo, flags, pitch); + } } static void radeon_fence_reference(struct pipe_winsys *ws, @@ -195,55 +264,6 @@ 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) -{ - 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) { struct radeon_winsys* radeon_ws; @@ -262,7 +282,7 @@ struct radeon_winsys* radeon_pipe_winsys(int fd) radeon_ws->priv->fd = fd; radeon_ws->priv->bom = radeon_bo_manager_gem_ctor(fd); - radeon_ws->base.flush_frontbuffer = radeon_flush_frontbuffer; + radeon_ws->base.flush_frontbuffer = NULL; /* overriden by co-state tracker */ radeon_ws->base.buffer_create = radeon_buffer_create; radeon_ws->base.user_buffer_create = radeon_buffer_user_create; @@ -277,60 +297,7 @@ struct radeon_winsys* radeon_pipe_winsys(int fd) radeon_ws->base.get_name = radeon_get_name; - return radeon_ws; -} -#if 0 -static struct pipe_buffer *radeon_buffer_from_handle(struct radeon_screen *radeon_screen, - uint32_t handle) -{ - struct radeon_pipe_buffer *radeon_buffer; - struct radeon_bo *bo = NULL; + radeon_ws->buffer_set_tiling = radeon_buffer_set_tiling; - bo = radeon_bo_open(radeon_screen->bom, handle, 0, 0, 0, 0); - if (bo == NULL) { - return NULL; - } - radeon_buffer = calloc(1, sizeof(struct radeon_pipe_buffer)); - if (radeon_buffer == NULL) { - radeon_bo_unref(bo); - return NULL; - } - pipe_reference_init(&radeon_buffer->base.reference, 1); - radeon_buffer->base.usage = PIPE_BUFFER_USAGE_PIXEL; - radeon_buffer->bo = bo; - return &radeon_buffer->base; -} - -struct pipe_surface *radeon_surface_from_handle(struct radeon_context *radeon_context, - uint32_t handle, - enum pipe_format format, - int w, int h, int pitch) -{ - struct pipe_screen *pipe_screen = radeon_context->pipe_screen; - struct pipe_winsys *pipe_winsys = radeon_context->pipe_winsys; - struct pipe_texture tmpl; - struct pipe_surface *ps; - struct pipe_texture *pt; - struct pipe_buffer *pb; - - pb = radeon_buffer_from_handle(radeon_context->radeon_screen, handle); - if (pb == NULL) { - return NULL; - } - memset(&tmpl, 0, sizeof(tmpl)); - tmpl.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET; - tmpl.target = PIPE_TEXTURE_2D; - tmpl.width0 = w; - tmpl.height0 = h; - tmpl.depth0 = 1; - tmpl.format = format; - - pt = pipe_screen->texture_blanket(pipe_screen, &tmpl, &pitch, pb); - if (pt == NULL) { - pipe_buffer_reference(&pb, NULL); - } - ps = pipe_screen->get_tex_surface(pipe_screen, pt, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); - return ps; + return radeon_ws; } -#endif diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h index bfe2221d1ed..f776e2d9008 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h @@ -30,26 +30,19 @@ #ifndef RADEON_BUFFER_H #define RADEON_BUFFER_H -#include <stdio.h> - -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_defines.h" -#include "pipe/p_inlines.h" - -//#include "state_tracker/st_public.h" - -#include "util/u_memory.h" +#include "pipebuffer/pb_buffer.h" #include "radeon_bo.h" #include "radeon_cs.h" -#include "radeon_drm.h" - #include "radeon_winsys.h" struct radeon_pipe_buffer { struct pipe_buffer base; + /* Pointer to GPU-backed BO. */ struct radeon_bo *bo; + /* Pointer to fallback PB buffer. */ + struct pb_buffer *pb; boolean flinked; uint32_t flink; }; @@ -68,6 +61,10 @@ struct radeon_winsys_priv { /* Current CS. */ struct radeon_cs* cs; + + /* 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 e2b451dc329..cd88deb992d 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.c @@ -30,7 +30,16 @@ */ #include "radeon_drm.h" -#include "r300_video_context.h" +#include "radeon_r300.h" +#include "radeon_buffer.h" + +#include "r300_winsys.h" +#include "trace/tr_drm.h" + +#include "util/u_memory.h" + +#include "xf86drm.h" +#include <sys/ioctl.h> /* Helper function to do the ioctls needed for setup and init. */ static void do_ioctls(int fd, struct radeon_winsys* winsys) @@ -39,12 +48,16 @@ static void do_ioctls(int fd, struct radeon_winsys* winsys) struct drm_radeon_info info = {0}; int target = 0; int retval; + drmVersionPtr version; info.value = (unsigned long)⌖ /* We do things in a specific order here. * - * First, the PCI ID. This is essential and should return usable numbers + * DRM version first. We need to be sure we're running on a KMS chipset. + * This is also for some features. + * + * Then, 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. * @@ -54,8 +67,18 @@ static void do_ioctls(int fd, struct radeon_winsys* winsys) * * 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 */ + * we don't actually use the info for anything yet. */ + + version = drmGetVersion(fd); + if (version->version_major != 2) { + fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is " + "only compatible with 2.x.x\n", __FUNCTION__, + version->version_major, version->version_minor, + version->version_patchlevel); + drmFreeVersion(version); + exit(1); + } + info.request = RADEON_INFO_DEVICE_ID; retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); if (retval) { @@ -91,16 +114,18 @@ static void do_ioctls(int fd, struct radeon_winsys* winsys) 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); + winsys->vram_size = gem_info.vram_size; + + debug_printf("radeon: Successfully grabbed chipset info from kernel!\n" + "radeon: DRM version: %d.%d.%d ID: 0x%04x GB: %d Z: %d\n" + "radeon: GART size: %d MB VRAM size: %d MB\n", + version->version_major, version->version_minor, + version->version_patchlevel, winsys->pci_id, + winsys->gb_pipes, winsys->z_pipes, + winsys->gart_size / 1024 / 1024, + winsys->vram_size / 1024 / 1024); + + drmFreeVersion(version); } /* Create a pipe_screen. */ @@ -108,28 +133,21 @@ 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); - do_ioctls(drmFB, winsys); - - if (debug_get_bool_option("RADEON_SOFTPIPE", FALSE)) { - return softpipe_create_screen((struct pipe_winsys*)winsys); + struct radeon_winsys* rwinsys = radeon_pipe_winsys(drmFB); + do_ioctls(drmFB, rwinsys); + + /* The state tracker can organize a softpipe fallback if no hw + * driver is found. + */ + if (is_r3xx(rwinsys->pci_id)) { + radeon_setup_winsys(drmFB, rwinsys); + return r300_create_screen(rwinsys); } else { - radeon_setup_winsys(drmFB, winsys); - return r300_create_screen(winsys); + FREE(rwinsys); + return NULL; } } -/* Create a pipe_context. */ -struct pipe_context* radeon_create_context(struct drm_api* api, - struct pipe_screen* screen) -{ - if (debug_get_bool_option("RADEON_SOFTPIPE", FALSE)) { - return radeon_create_softpipe(screen->winsys); - } else { - return r300_create_context(screen, - (struct radeon_winsys*)screen->winsys); - } -} static struct pipe_video_context * @@ -150,12 +168,13 @@ radeon_create_video_context(struct drm_api *api, struct pipe_screen *pscreen, } boolean radeon_buffer_from_texture(struct drm_api* api, + struct pipe_screen* screen, struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride) { /* XXX fix this */ - return r300_get_texture_buffer(texture, buffer, stride); + return r300_get_texture_buffer(screen, texture, buffer, stride); } /* Create a buffer from a handle. */ @@ -220,9 +239,9 @@ 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)) { + if (!radeon_buffer_from_texture(api, screen, texture, &buffer, stride)) { return FALSE; } @@ -253,8 +272,8 @@ static boolean radeon_local_handle_from_texture(struct drm_api *api, unsigned *stride, unsigned *handle) { - struct pipe_buffer *buffer; - if (!radeon_buffer_from_texture(api, texture, &buffer, stride)) { + struct pipe_buffer *buffer = NULL; + if (!radeon_buffer_from_texture(api, screen, texture, &buffer, stride)) { return FALSE; } @@ -265,13 +284,19 @@ static boolean radeon_local_handle_from_texture(struct drm_api *api, return TRUE; } +static void radeon_drm_api_destroy(struct drm_api *api) +{ + return; +} + struct drm_api drm_api_hooks = { + .name = "radeon", + .driver_name = "radeon", .create_screen = radeon_create_screen, - .create_context = radeon_create_context, - .create_video_context = radeon_create_video_context, .texture_from_shared_handle = radeon_texture_from_shared_handle, .shared_handle_from_texture = radeon_shared_handle_from_texture, .local_handle_from_texture = radeon_local_handle_from_texture, + .destroy = radeon_drm_api_destroy, }; struct drm_api* drm_api_create() diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.h b/src/gallium/winsys/drm/radeon/core/radeon_drm.h index 9a789ec1a45..f62a9b80485 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.h @@ -30,33 +30,16 @@ #ifndef RADEON_DRM_H #define RADEON_DRM_H -#include <sys/ioctl.h> - -#include "xf86drm.h" - -#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" struct pipe_screen* radeon_create_screen(struct drm_api* api, int drmFB, struct drm_create_screen_arg *arg); -struct pipe_context* radeon_create_context(struct drm_api* api, - struct pipe_screen* screen); boolean radeon_buffer_from_texture(struct drm_api* api, + struct pipe_screen* screen, struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride); @@ -77,4 +60,13 @@ boolean radeon_global_handle_from_buffer(struct drm_api* api, unsigned* handle); void radeon_destroy_drm_api(struct drm_api* api); + +/* Guess at whether this chipset should use r300g. + * + * I believe that this check is valid, but I haven't been exhaustive. */ +static INLINE boolean is_r3xx(int pciid) +{ + return (pciid > 0x3150) && (pciid < 0x796f); +} + #endif diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.c b/src/gallium/winsys/drm/radeon/core/radeon_r300.c index ba0596c30dc..122bd213543 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.c @@ -21,11 +21,16 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "radeon_r300.h" +#include "radeon_buffer.h" + +#include "radeon_cs_gem.h" 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); } @@ -79,9 +84,13 @@ static void radeon_write_cs_reloc(struct radeon_winsys* winsys, uint32_t flags) { int retval = 0; + struct radeon_pipe_buffer* radeon_buffer = + (struct radeon_pipe_buffer*)pbuffer; + + assert(!radeon_buffer->pb); - retval = radeon_cs_write_reloc(winsys->priv->cs, - ((struct radeon_pipe_buffer*)pbuffer)->bo, rd, wd, flags); + retval = radeon_cs_write_reloc(winsys->priv->cs, radeon_buffer->bo, + rd, wd, flags); if (retval) { debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n", @@ -106,6 +115,11 @@ static void radeon_flush_cs(struct radeon_winsys* winsys) { int retval; + /* Don't flush a zero-sized CS. */ + if (!winsys->priv->cs->cdw) { + return; + } + /* Emit the CS. */ retval = radeon_cs_emit(winsys->priv->cs); if (retval) { diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.h b/src/gallium/winsys/drm/radeon/core/radeon_r300.h index cfbdb302661..e655dc32c85 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.h @@ -23,16 +23,7 @@ #ifndef RADEON_R300_H #define RADEON_R300_H -/* XXX WTF is this! I shouldn't have to include those first three! FUCK! */ -#include <stdint.h> -#include <stdlib.h> -#include "drm.h" -#include "radeon_drm.h" -#include "radeon_cs_gem.h" - -#include "r300_winsys.h" - -#include "radeon_buffer.h" +#include "radeon_winsys.h" void radeon_setup_winsys(int fd, struct radeon_winsys* winsys); diff --git a/src/gallium/winsys/drm/radeon/core/radeon_winsys.h b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h index 9edc9e038c3..4901080ca7b 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_winsys.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h @@ -30,7 +30,7 @@ #ifndef RADEON_WINSYS_H #define RADEON_WINSYS_H -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" struct radeon_winsys_priv; @@ -100,6 +100,12 @@ struct radeon_winsys { void (*flush_cb)(void *), void *data); void (*reset_bos)(struct radeon_winsys *winsys); + + void (*buffer_set_tiling)(struct radeon_winsys* winsys, + struct pipe_buffer* buffer, + uint32_t pitch, + boolean microtiled, + boolean macrotiled); }; #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/Makefile b/src/gallium/winsys/drm/radeon/dri/Makefile index a9889444de8..d75f7dd6da7 100644 --- a/src/gallium/winsys/drm/radeon/dri/Makefile +++ b/src/gallium/winsys/drm/radeon/dri/Makefile @@ -2,9 +2,7 @@ TOP = ../../../../../.. include $(TOP)/configs/current -LIBNAME = radeon_dri.so - -MINIGLX_SOURCES = +LIBNAME = radeong_dri.so PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ 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/egl/Makefile b/src/gallium/winsys/drm/radeon/egl/Makefile index 6a1448d1b9b..cd4f9b20f06 100644 --- a/src/gallium/winsys/drm/radeon/egl/Makefile +++ b/src/gallium/winsys/drm/radeon/egl/Makefile @@ -1,26 +1,14 @@ TOP = ../../../../../.. -GALLIUMDIR = ../../../.. include $(TOP)/configs/current -LIBNAME = EGL_r300.so +EGL_DRIVER_NAME = radeon +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -ldrm_radeon -PIPE_DRIVERS = \ - $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ - $(GALLIUMDIR)/winsys/drm/radeon/core/libradeonwinsys.a \ +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/radeon/core/libradeonwinsys.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/r300/libr300.a -DRIVER_SOURCES = - -C_SOURCES = \ - $(COMMON_GALLIUM_SOURCES) \ - $(DRIVER_SOURCES) - -DRIVER_EXTRAS = -ldrm_radeon - -ASM_SOURCES = - -include ../../Makefile.template - -symlinks: +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/radeon/egl/dummy.c b/src/gallium/winsys/drm/radeon/egl/dummy.c new file mode 100644 index 00000000000..3181d0ba7e8 --- /dev/null +++ b/src/gallium/winsys/drm/radeon/egl/dummy.c @@ -0,0 +1,3 @@ +/* A poor man's --whole-archive for EGL drivers */ +void *_eglMain(void *); +void *_eglWholeArchive = (void *) _eglMain; diff --git a/src/gallium/winsys/drm/radeon/python/README b/src/gallium/winsys/drm/radeon/python/README index d9e49bce67b..339836a592b 100644 --- a/src/gallium/winsys/drm/radeon/python/README +++ b/src/gallium/winsys/drm/radeon/python/README @@ -12,4 +12,4 @@ Run as: export PYTHONPATH=$PWD/build/linux-x86-debug/gallium/winsys/drm/radeon/python:$PWD/build/linux-x86-debug/gallium/state_trackers/python - python src/gallium/state_trackers/python/samples/tri.py + python progs/gallium/python/samples/tri.py 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/python/radeon_hardpipe_winsys.c b/src/gallium/winsys/drm/radeon/python/radeon_hardpipe_winsys.c index c3ec24aaf78..fc63081a4cc 100644 --- a/src/gallium/winsys/drm/radeon/python/radeon_hardpipe_winsys.c +++ b/src/gallium/winsys/drm/radeon/python/radeon_hardpipe_winsys.c @@ -124,17 +124,9 @@ error: } -static struct pipe_context * -radeon_hardpipe_context_create(struct pipe_screen *screen) -{ - /* FIXME: create a radon pipe_context from screen */ - - return NULL; -} const struct st_winsys st_hardpipe_winsys = { &radeon_hardpipe_screen_create, - &radeon_hardpipe_context_create, }; 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/swrast/Makefile b/src/gallium/winsys/drm/swrast/Makefile new file mode 100644 index 00000000000..363b89584f2 --- /dev/null +++ b/src/gallium/winsys/drm/swrast/Makefile @@ -0,0 +1,12 @@ +# src/gallium/winsys/drm/swrast/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/swrast/core/Makefile b/src/gallium/winsys/drm/swrast/core/Makefile new file mode 100644 index 00000000000..93931ae22b9 --- /dev/null +++ b/src/gallium/winsys/drm/swrast/core/Makefile @@ -0,0 +1,10 @@ +# src/gallium/winsys/drm/swrast/core/Makefile + +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBNAME = swrastdrm + +C_SOURCES = swrast_drm_api.c + +include ../../../../Makefile.template diff --git a/src/gallium/winsys/drm/swrast/core/swrast_drm_api.c b/src/gallium/winsys/drm/swrast/core/swrast_drm_api.c new file mode 100644 index 00000000000..8c9f80e2c15 --- /dev/null +++ b/src/gallium/winsys/drm/swrast/core/swrast_drm_api.c @@ -0,0 +1,13 @@ +#include "state_tracker/drm_api.h" + +static struct drm_api swrast_drm_api = +{ + .name = "swrast", +}; + +struct drm_api * +drm_api_create() +{ + (void) swrast_drm_api; + return NULL; +} diff --git a/src/gallium/winsys/drm/swrast/egl/Makefile b/src/gallium/winsys/drm/swrast/egl/Makefile new file mode 100644 index 00000000000..26fe2d2805a --- /dev/null +++ b/src/gallium/winsys/drm/swrast/egl/Makefile @@ -0,0 +1,12 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +EGL_DRIVER_NAME = swrast +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = + +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/swrast/core/libswrastdrm.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a + +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/swrast/egl/dummy.c b/src/gallium/winsys/drm/swrast/egl/dummy.c new file mode 100644 index 00000000000..3181d0ba7e8 --- /dev/null +++ b/src/gallium/winsys/drm/swrast/egl/dummy.c @@ -0,0 +1,3 @@ +/* A poor man's --whole-archive for EGL drivers */ +void *_eglMain(void *); +void *_eglWholeArchive = (void *) _eglMain; diff --git a/src/gallium/winsys/drm/vmware/core/vmw_buffer.c b/src/gallium/winsys/drm/vmware/core/vmw_buffer.c index b812fb59d39..eca174a6c56 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_buffer.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_buffer.c @@ -41,7 +41,7 @@ #include "svga_cmd.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_memory.h" #include "pipebuffer/pb_buffer.h" #include "pipebuffer/pb_bufmgr.h" diff --git a/src/gallium/winsys/drm/vmware/core/vmw_buffer.h b/src/gallium/winsys/drm/vmware/core/vmw_buffer.h index 634bdcabd26..41fb4476da5 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_buffer.h +++ b/src/gallium/winsys/drm/vmware/core/vmw_buffer.h @@ -27,7 +27,7 @@ #ifndef VMW_BUFFER_H_ #define VMW_BUFFER_H_ - +#include <assert.h> #include "pipe/p_compiler.h" struct SVGAGuestPtr; diff --git a/src/gallium/winsys/drm/vmware/core/vmw_context.c b/src/gallium/winsys/drm/vmware/core/vmw_context.c index b6997588de4..90ffc4868f7 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_context.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_context.c @@ -41,9 +41,18 @@ #define VMW_COMMAND_SIZE (64*1024) #define VMW_SURFACE_RELOCS (1024) +#define VMW_REGION_RELOCS (512) #define VMW_MUST_FLUSH_STACK 8 +struct vmw_region_relocation +{ + struct SVGAGuestPtr *where; + struct pb_buffer *buffer; + /* TODO: put offset info inside where */ + uint32 offset; +}; + struct vmw_svga_winsys_context { struct svga_winsys_context base; @@ -69,10 +78,31 @@ struct vmw_svga_winsys_context uint32_t staged; uint32_t reserved; } surface; + + struct { + struct vmw_region_relocation relocs[VMW_REGION_RELOCS]; + uint32_t size; + uint32_t used; + uint32_t staged; + uint32_t reserved; + } region; struct pb_validate *validate; uint32_t last_fence; + + /** + * The amount of GMR that is referred by the commands currently batched + * in the context. + */ + uint32_t seen_regions; + + /** + * Whether this context should fail to reserve more commands, not because it + * ran out of command space, but because a substantial ammount of GMR was + * referred. + */ + boolean preemptive_flush; }; @@ -96,6 +126,19 @@ vmw_swc_flush(struct svga_winsys_context *swc, ret = pb_validate_validate(vswc->validate); assert(ret == PIPE_OK); if(ret == PIPE_OK) { + + /* Apply relocations */ + for(i = 0; i < vswc->region.used; ++i) { + struct vmw_region_relocation *reloc = &vswc->region.relocs[i]; + struct SVGAGuestPtr ptr; + + if(!vmw_gmr_bufmgr_region_ptr(reloc->buffer, &ptr)) + assert(0); + + ptr.offset += reloc->offset; + + *reloc->where = ptr; + } if (vswc->command.used) vmw_ioctl_command(vswc->vws, @@ -121,9 +164,18 @@ vmw_swc_flush(struct svga_winsys_context *swc, vswc->surface.used = 0; vswc->surface.reserved = 0; + for(i = 0; i < vswc->region.used + vswc->region.staged; ++i) { + pb_reference(&vswc->region.relocs[i].buffer, NULL); + } + + vswc->region.used = 0; + vswc->region.reserved = 0; + #ifdef DEBUG vswc->must_flush = FALSE; #endif + vswc->preemptive_flush = FALSE; + vswc->seen_regions = 0; if(pfence) *pfence = fence; @@ -151,8 +203,10 @@ vmw_swc_reserve(struct svga_winsys_context *swc, 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) { + if(vswc->preemptive_flush || + vswc->command.used + nr_bytes > vswc->command.size || + vswc->surface.used + nr_relocs > vswc->surface.size || + vswc->region.used + nr_relocs > vswc->region.size) { #ifdef DEBUG vswc->must_flush = TRUE; debug_backtrace_capture(vswc->must_flush_stack, 1, @@ -163,11 +217,14 @@ vmw_swc_reserve(struct svga_winsys_context *swc, assert(vswc->command.used + nr_bytes <= vswc->command.size); assert(vswc->surface.used + nr_relocs <= vswc->surface.size); - + assert(vswc->region.used + nr_relocs <= vswc->region.size); + vswc->command.reserved = nr_bytes; vswc->surface.reserved = nr_relocs; vswc->surface.staged = 0; - + vswc->region.reserved = nr_relocs; + vswc->region.staged = 0; + return vswc->command.buffer + vswc->command.used; } @@ -206,20 +263,41 @@ vmw_swc_region_relocation(struct svga_winsys_context *swc, unsigned flags) { struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); - struct SVGAGuestPtr ptr; - struct pb_buffer *buf = vmw_pb_buffer(buffer); + struct vmw_region_relocation *reloc; enum pipe_error ret; + + assert(vswc->region.staged < vswc->region.reserved); - if(!vmw_gmr_bufmgr_region_ptr(buf, &ptr)) - assert(0); - - ptr.offset += offset; + reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged]; + reloc->where = where; + pb_reference(&reloc->buffer, vmw_pb_buffer(buffer)); + reloc->offset = offset; - *where = ptr; + ++vswc->region.staged; - ret = pb_validate_add_buffer(vswc->validate, buf, flags); + ret = pb_validate_add_buffer(vswc->validate, reloc->buffer, flags); /* TODO: Update pipebuffer to reserve buffers and not fail here */ assert(ret == PIPE_OK); + + /* + * Flush preemptively the FIFO commands to keep the GMR working set within + * the GMR pool size. + * + * This is necessary for applications like SPECviewperf that generate huge + * amounts of immediate vertex data, so that we don't pile up too much of + * that vertex data neither in the guest nor in the host. + * + * Note that in the current implementation if a region is referred twice in + * a command stream, it will be accounted twice. We could detect repeated + * regions and count only once, but there is no incentive to do that, since + * regions are typically short-lived; always referred in a single command; + * and at the worst we just flush the commands a bit sooner, which for the + * SVGA virtual device it's not a performance issue since flushing commands + * to the FIFO won't cause flushing in the host. + */ + vswc->seen_regions += reloc->buffer->base.size; + if(vswc->seen_regions >= VMW_GMR_POOL_SIZE/2) + vswc->preemptive_flush = TRUE; } @@ -238,6 +316,12 @@ vmw_swc_commit(struct svga_winsys_context *swc) vswc->surface.used += vswc->surface.staged; vswc->surface.staged = 0; vswc->surface.reserved = 0; + + assert(vswc->region.staged <= vswc->region.reserved); + assert(vswc->region.used + vswc->region.staged <= vswc->region.size); + vswc->region.used += vswc->region.staged; + vswc->region.staged = 0; + vswc->region.reserved = 0; } @@ -246,6 +330,11 @@ 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->region.used; ++i) { + pb_reference(&vswc->region.relocs[i].buffer, NULL); + } + 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); @@ -279,6 +368,7 @@ vmw_svga_winsys_context_create(struct svga_winsys_screen *sws) vswc->command.size = VMW_COMMAND_SIZE; vswc->surface.size = VMW_SURFACE_RELOCS; + vswc->region.size = VMW_REGION_RELOCS; vswc->validate = pb_validate_create(); if(!vswc->validate) { @@ -290,8 +380,3 @@ vmw_svga_winsys_context_create(struct svga_winsys_screen *sws) } -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 index 305ce9b5bec..d4884d24e99 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_context.h +++ b/src/gallium/winsys/drm/vmware/core/vmw_context.h @@ -52,8 +52,5 @@ struct pipe_screen; 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_screen.c b/src/gallium/winsys/drm/vmware/core/vmw_screen.c index 911eec5e254..6cc9b382932 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_screen.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen.c @@ -37,13 +37,16 @@ * module. */ struct vmw_winsys_screen * -vmw_winsys_create( int fd ) +vmw_winsys_create( int fd, boolean use_old_scanout_flag ) { struct vmw_winsys_screen *vws = CALLOC_STRUCT(vmw_winsys_screen); if (!vws) goto out_no_vws; vws->ioctl.drm_fd = fd; + vws->use_old_scanout_flag = use_old_scanout_flag; + debug_printf("%s: use_old_scanout_flag == %s\n", __FUNCTION__, + use_old_scanout_flag ? "true" : "false"); if (!vmw_ioctl_init(vws)) goto out_no_ioctl; diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen.h b/src/gallium/winsys/drm/vmware/core/vmw_screen.h index a875107370c..d3f2c2c7f56 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_screen.h +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen.h @@ -40,6 +40,10 @@ #include "svga_winsys.h" + +#define VMW_GMR_POOL_SIZE (16*1024*1024) + + struct pb_manager; struct vmw_region; @@ -48,6 +52,8 @@ struct vmw_winsys_screen { struct svga_winsys_screen base; + boolean use_old_scanout_flag; + struct { volatile uint32_t *fifo_map; uint64_t last_fence; @@ -127,7 +133,7 @@ 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); +struct vmw_winsys_screen *vmw_winsys_create(int fd, boolean use_old_scanout_flag); void vmw_winsys_destroy(struct vmw_winsys_screen *sws); diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c b/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c index 5995eee34ba..a7c6e88b9eb 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c @@ -25,8 +25,9 @@ #include "pipe/p_compiler.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_memory.h" +#include "util/u_format.h" #include "vmw_screen.h" #include "trace/tr_drm.h" @@ -48,8 +49,9 @@ 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 struct dri1_api_version drm_required = { 1, 0, 0 }; +static struct dri1_api_version drm_compat = { 1, 0, 0 }; +static struct dri1_api_version drm_scanout = { 0, 9, 0 }; static boolean vmw_dri1_check_version(const struct dri1_api_version *cur, @@ -84,6 +86,29 @@ vmw_drm_create_screen(struct drm_api *drm_api, struct vmw_winsys_screen *vws; struct pipe_screen *screen; struct dri1_create_screen_arg *dri1; + boolean use_old_scanout_flag = FALSE; + + if (!arg || arg->mode == DRM_CREATE_NORMAL) { + struct dri1_api_version drm_ver; + drmVersionPtr ver; + + ver = drmGetVersion(fd); + if (ver == NULL) + return NULL; + + drm_ver.major = ver->version_major; + drm_ver.minor = ver->version_minor; + drm_ver.patch_level = 0; /* ??? */ + + drmFreeVersion(ver); + if (!vmw_dri1_check_version(&drm_ver, &drm_required, + &drm_compat, "vmwgfx drm driver")) + return NULL; + + if (!vmw_dri1_check_version(&drm_ver, &drm_scanout, + &drm_compat, "use old scanout field (not a error)")) + use_old_scanout_flag = TRUE; + } if (arg != NULL) { switch (arg->mode) { @@ -100,6 +125,9 @@ vmw_drm_create_screen(struct drm_api *drm_api, if (!vmw_dri1_check_version(&dri1->drm_version, &drm_required, &drm_compat, "vmwgfx drm driver")) return NULL; + if (!vmw_dri1_check_version(&dri1->drm_version, &drm_scanout, + &drm_compat, "use old scanout field (not a error)")) + use_old_scanout_flag = TRUE; dri1->api = &dri1_api_hooks; break; default: @@ -107,7 +135,7 @@ vmw_drm_create_screen(struct drm_api *drm_api, } } - vws = vmw_winsys_create( fd ); + vws = vmw_winsys_create( fd, use_old_scanout_flag ); if (!vws) goto out_no_vws; @@ -220,22 +248,19 @@ vmw_dri1_present_locked(struct pipe_context *locked_pipe, 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) +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 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; + struct pipe_texture *tex; union drm_vmw_surface_reference_arg arg; struct drm_vmw_surface_arg *req = &arg.req; struct drm_vmw_surface_create_req *rep = &arg.rep; @@ -282,43 +307,28 @@ vmw_drm_buffer_from_handle(struct drm_api *drm_api, pipe_reference_init(&vsrf->refcnt, 1); p_atomic_set(&vsrf->validated, 0); + vsrf->screen = vws; vsrf->sid = handle; ssrf = svga_winsys_surface(vsrf); - buf = svga_screen_buffer_wrap_surface(screen, rep->format, ssrf); - if (!buf) + tex = svga_screen_texture_wrap_surface(screen, templat, rep->format, ssrf); + if (!tex) vmw_svga_winsys_surface_reference(&vsrf, NULL); - return buf; + return tex; 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, +vmw_drm_handle_from_texture(struct drm_api *drm_api, struct pipe_screen *screen, - struct pipe_buffer *buffer, + struct pipe_texture *texture, + unsigned *stride, unsigned *handle) { struct svga_winsys_surface *surface = - svga_screen_buffer_get_winsys_surface(buffer); + svga_screen_texture_get_winsys_surface(texture); struct vmw_svga_winsys_surface *vsrf; if (!surface) @@ -326,31 +336,13 @@ vmw_drm_handle_from_buffer(struct drm_api *drm_api, vsrf = vmw_svga_winsys_surface(surface); *handle = vsrf->sid; + *stride = util_format_get_nblocksx(texture->format, texture->width0) * + util_format_get_blocksize(texture->format); + 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, @@ -358,8 +350,9 @@ static struct dri1_api dri1_api_hooks = { }; static struct drm_api vmw_drm_api_hooks = { + .name = "vmwgfx", + .driver_name = "vmwgfx", .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, diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen_ioctl.c b/src/gallium/winsys/drm/vmware/core/vmw_screen_ioctl.c index 51e455f9254..5d81fa8c4a6 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_screen_ioctl.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_ioctl.c @@ -57,6 +57,12 @@ struct vmw_region uint32_t size; }; +/* XXX: This isn't a real hardware flag, but just a hack for kernel to + * know about primary surfaces. In newer versions of the kernel + * interface the driver uses a special field. + */ +#define SVGA3D_SURFACE_HINT_SCANOUT (1 << 9) + static void vmw_check_last_cmd(struct vmw_winsys_screen *vws) { @@ -169,7 +175,17 @@ vmw_ioctl_surface_create(struct vmw_winsys_screen *vws, vmw_printf("%s flags %d format %d\n", __FUNCTION__, flags, format); memset(&s_arg, 0, sizeof(s_arg)); - req->flags = (uint32_t) flags; + if (vws->use_old_scanout_flag && + (flags & SVGA3D_SURFACE_HINT_SCANOUT)) { + req->flags = (uint32_t) flags; + req->scanout = false; + } else if (flags & SVGA3D_SURFACE_HINT_SCANOUT) { + req->flags = (uint32_t) (flags & ~SVGA3D_SURFACE_HINT_SCANOUT); + req->scanout = true; + } else { + req->flags = (uint32_t) flags; + req->scanout = false; + } req->format = (uint32_t) format; req->shareable = 1; @@ -468,6 +484,15 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws) 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)); diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen_pools.c b/src/gallium/winsys/drm/vmware/core/vmw_screen_pools.c index b1c24b0cb6a..b9823d78575 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_screen_pools.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_pools.c @@ -53,14 +53,32 @@ vmw_pools_init(struct vmw_winsys_screen *vws) goto error; vws->pools.gmr_mm = mm_bufmgr_create(vws->pools.gmr, - 16*1024*1024, + VMW_GMR_POOL_SIZE, 12 /* 4096 alignment */); if(!vws->pools.gmr_mm) goto error; + /* + * GMR buffers are typically shortlived, but it's possible that at a given + * instance a buffer is mapped. So to avoid stalling we tell pipebuffer to + * forbid creation of buffers beyond half the GMR pool size, + * + * XXX: It is unclear weather we want to limit the total amount of temporary + * malloc memory used to backup unvalidated GMR buffers. On one hand it is + * preferrable to fail an allocation than exhausting the guest memory with + * temporary data, but on the other hand it is possible that a stupid + * application creates large vertex buffers and does not use them for a long + * time -- since the svga pipe driver only emits the DMA uploads when a + * buffer is used for drawing this would effectively disabling swapping GMR + * buffers to memory. So far, the preemptively flush already seems to keep + * total allocated memory within relatively small numbers, so we don't + * limit. + */ vws->pools.gmr_fenced = fenced_bufmgr_create( vws->pools.gmr_mm, - vmw_fence_ops_create(vws)); + vmw_fence_ops_create(vws), + VMW_GMR_POOL_SIZE/2, + ~0); #ifdef DEBUG vws->pools.gmr_fenced = pb_debug_manager_create(vws->pools.gmr_fenced, diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen_svga.c b/src/gallium/winsys/drm/vmware/core/vmw_screen_svga.c index d7d008859b3..2b4e80f0039 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_screen_svga.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_svga.c @@ -36,7 +36,7 @@ #include "svga_cmd.h" #include "svga3d_caps.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" #include "pipebuffer/pb_buffer.h" diff --git a/src/gallium/winsys/drm/vmware/core/vmw_surface.c b/src/gallium/winsys/drm/vmware/core/vmw_surface.c index 64eb32f8b94..5f1b9ad5770 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_surface.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_surface.c @@ -47,7 +47,7 @@ vmw_svga_winsys_surface_reference(struct vmw_svga_winsys_surface **pdst, src_ref = src ? &src->refcnt : NULL; dst_ref = dst ? &dst->refcnt : NULL; - if (pipe_reference(&dst_ref, src_ref)) { + if (pipe_reference(dst_ref, src_ref)) { vmw_ioctl_surface_destroy(dst->screen, dst->sid); #ifdef DEBUG /* to detect dangling pointers */ diff --git a/src/gallium/winsys/drm/vmware/core/vmw_surface.h b/src/gallium/winsys/drm/vmware/core/vmw_surface.h index 340cc1532e0..3d61595c288 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_surface.h +++ b/src/gallium/winsys/drm/vmware/core/vmw_surface.h @@ -36,8 +36,8 @@ #include "pipe/p_compiler.h" -#include "pipe/p_atomic.h" -#include "pipe/p_refcnt.h" +#include "util/u_atomic.h" +#include "util/u_inlines.h" #define VMW_MAX_PRESENTS 3 @@ -45,7 +45,7 @@ struct vmw_svga_winsys_surface { - struct pipe_atomic validated; + int32_t validated; /* atomic */ struct pipe_reference refcnt; struct vmw_winsys_screen *screen; diff --git a/src/gallium/winsys/drm/vmware/core/vmwgfx_drm.h b/src/gallium/winsys/drm/vmware/core/vmwgfx_drm.h index 6bf3183ff54..47914bdb711 100644 --- a/src/gallium/winsys/drm/vmware/core/vmwgfx_drm.h +++ b/src/gallium/winsys/drm/vmware/core/vmwgfx_drm.h @@ -25,40 +25,51 @@ * **************************************************************************/ -#ifndef _VMWGFX_DRM_H_ -#define _VMWGFX_DRM_H_ +#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 1 -#define DRM_VMW_EXTENSION 2 -#define DRM_VMW_CREATE_CONTEXT 3 -#define DRM_VMW_UNREF_CONTEXT 4 -#define DRM_VMW_CREATE_SURFACE 5 -#define DRM_VMW_UNREF_SURFACE 6 -#define DRM_VMW_REF_SURFACE 7 -#define DRM_VMW_EXECBUF 8 -#define DRM_VMW_ALLOC_DMABUF 9 -#define DRM_VMW_UNREF_DMABUF 10 -#define DRM_VMW_FIFO_DEBUG 11 -#define DRM_VMW_FENCE_WAIT 12 -#define DRM_VMW_OVERLAY 13 +#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. * - * Currently we support only one parameter: - * * 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_FIFO_OFFSET 0 +#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 +#define DRM_VMW_PARAM_HW_CAPS 4 +#define DRM_VMW_PARAM_FIFO_CAPS 5 /** * struct drm_vmw_getparam_arg @@ -77,49 +88,6 @@ struct drm_vmw_getparam_arg { /*************************************************************************/ /** - * 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 @@ -171,6 +139,8 @@ struct drm_vmw_context_arg { * 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. + * @scanout: Boolean whether the surface is intended to be used as a + * scanout. * * Input data to the DRM_VMW_CREATE_SURFACE Ioctl. * Output data from the DRM_VMW_REF_SURFACE Ioctl. @@ -182,7 +152,7 @@ struct drm_vmw_surface_create_req { uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES]; uint64_t size_addr; int32_t shareable; - uint32_t pad64; + int32_t scanout; }; /** @@ -285,17 +255,28 @@ union drm_vmw_surface_reference_arg { * * @commands: User-space address of a command buffer cast to an uint64_t. * @command-size: Size in bytes of the command buffer. + * @throttle-us: Sleep until software is less than @throttle_us + * microseconds ahead of hardware. The driver may round this value + * to the nearest kernel tick. * @fence_rep: User-space address of a struct drm_vmw_fence_rep cast to an * uint64_t. + * @version: Allows expanding the execbuf ioctl parameters without breaking + * backwards compatibility, since user-space will always tell the kernel + * which version it uses. + * @flags: Execbuf flags. None currently. * * Argument to the DRM_VMW_EXECBUF Ioctl. */ +#define DRM_VMW_EXECBUF_VERSION 0 + struct drm_vmw_execbuf_arg { uint64_t commands; uint32_t command_size; - uint32_t pad64; + uint32_t throttle_us; uint64_t fence_rep; + uint32_t version; + uint32_t flags; }; /** @@ -441,7 +422,7 @@ struct drm_vmw_fence_wait_arg { /*************************************************************************/ /** - * DRM_VMW_OVERLAY - Control overlays. + * 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 @@ -466,7 +447,7 @@ struct drm_vmw_rect { }; /** - * struct drm_vmw_overlay_arg + * struct drm_vmw_control_stream_arg * * @stream_id: Stearm to control * @enabled: If false all following arguments are ignored. @@ -480,10 +461,10 @@ struct drm_vmw_rect { * @src: Source rect, must be within the defined area above. * @dst: Destination rect, x and y may be negative. * - * Argument to the DRM_VMW_OVERLAY Ioctl. + * Argument to the DRM_VMW_CONTROL_STREAM Ioctl. */ -struct drm_vmw_overlay_arg { +struct drm_vmw_control_stream_arg { uint32_t stream_id; uint32_t enabled; @@ -503,4 +484,62 @@ struct drm_vmw_overlay_arg { 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/SConscript b/src/gallium/winsys/drm/vmware/dri/SConscript index 1019f577a5f..84319f91ff1 100644 --- a/src/gallium/winsys/drm/vmware/dri/SConscript +++ b/src/gallium/winsys/drm/vmware/dri/SConscript @@ -48,7 +48,7 @@ if env['platform'] == 'linux': svgadrm, svga, mesa, - auxiliaries, + gallium, ]) # TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions diff --git a/src/gallium/winsys/drm/vmware/egl/Makefile b/src/gallium/winsys/drm/vmware/egl/Makefile index 8e2980c318c..a3e73131c35 100644 --- a/src/gallium/winsys/drm/vmware/egl/Makefile +++ b/src/gallium/winsys/drm/vmware/egl/Makefile @@ -1,18 +1,14 @@ - TOP = ../../../../../.. include $(TOP)/configs/current -LIBNAME = EGL_svga.so +EGL_DRIVER_NAME = vmwgfx +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -PIPE_DRIVERS = \ - $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ +EGL_DRIVER_PIPES = \ $(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/svga/libsvga.a -C_SOURCES = \ - $(COMMON_GALLIUM_SOURCES) - -include ../../Makefile.template - -symlinks: +include ../../Makefile.egl diff --git a/src/gallium/winsys/drm/vmware/egl/dummy.c b/src/gallium/winsys/drm/vmware/egl/dummy.c new file mode 100644 index 00000000000..3181d0ba7e8 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/egl/dummy.c @@ -0,0 +1,3 @@ +/* A poor man's --whole-archive for EGL drivers */ +void *_eglMain(void *); +void *_eglWholeArchive = (void *) _eglMain; diff --git a/src/gallium/winsys/drm/vmware/xorg/SConscript b/src/gallium/winsys/drm/vmware/xorg/SConscript index ff7b2ed34ed..1e5d8ff7fed 100644 --- a/src/gallium/winsys/drm/vmware/xorg/SConscript +++ b/src/gallium/winsys/drm/vmware/xorg/SConscript @@ -38,10 +38,13 @@ if env['platform'] == 'linux': st_xorg, svgadrm, svga, - auxiliaries, + gallium, ]) sources = [ + 'vmw_ioctl.c', + 'vmw_screen.c', + 'vmw_video.c', 'vmw_xorg.c', ] diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_driver.h b/src/gallium/winsys/drm/vmware/xorg/vmw_driver.h index 04d446a2dfb..ba754b51e47 100644 --- a/src/gallium/winsys/drm/vmware/xorg/vmw_driver.h +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_driver.h @@ -40,19 +40,23 @@ struct vmw_dma_buffer; -struct vmw_driver +struct vmw_customizer { + CustomizerRec base; + ScrnInfoPtr pScrn; + int fd; + void *cursor_priv; + /* vmw_video.c */ void *video_priv; }; -static INLINE struct vmw_driver * -vmw_driver(ScrnInfoPtr pScrn) +static INLINE struct vmw_customizer * +vmw_customizer(CustomizerPtr cust) { - modesettingPtr ms = modesettingPTR(pScrn); - return ms ? (struct vmw_driver *)ms->winsys_priv : NULL; + return cust ? (struct vmw_customizer *) cust : NULL; } @@ -60,27 +64,40 @@ vmw_driver(ScrnInfoPtr pScrn) * vmw_video.c */ -Bool vmw_video_init(ScrnInfoPtr pScrn, struct vmw_driver *vmw); +Bool vmw_video_init(struct vmw_customizer *vmw); -Bool vmw_video_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw); +Bool vmw_video_close(struct vmw_customizer *vmw); + +void vmw_video_stop_all(struct vmw_customizer *vmw); /*********************************************************************** * vmw_ioctl.c */ -struct vmw_dma_buffer * vmw_ioctl_buffer_create(struct vmw_driver *vmw, +int vmw_ioctl_cursor_bypass(struct vmw_customizer *vmw, int xhot, int yhot); + +struct vmw_dma_buffer * vmw_ioctl_buffer_create(struct vmw_customizer *vmw, uint32_t size, unsigned *handle); -void * vmw_ioctl_buffer_map(struct vmw_driver *vmw, +void * vmw_ioctl_buffer_map(struct vmw_customizer *vmw, struct vmw_dma_buffer *buf); -void vmw_ioctl_buffer_unmap(struct vmw_driver *vmw, +void vmw_ioctl_buffer_unmap(struct vmw_customizer *vmw, struct vmw_dma_buffer *buf); -void vmw_ioctl_buffer_destroy(struct vmw_driver *vmw, +void vmw_ioctl_buffer_destroy(struct vmw_customizer *vmw, struct vmw_dma_buffer *buf); +int vmw_ioctl_supports_streams(struct vmw_customizer *vmw); + +int vmw_ioctl_num_streams(struct vmw_customizer *vmw, + uint32_t *ntot, uint32_t *nfree); + +int vmw_ioctl_unref_stream(struct vmw_customizer *vmw, uint32_t stream_id); + +int vmw_ioctl_claim_stream(struct vmw_customizer *vmw, uint32_t *out); + #endif diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_ioctl.c b/src/gallium/winsys/drm/vmware/xorg/vmw_ioctl.c index 3cac5b7760c..521578ab35d 100644 --- a/src/gallium/winsys/drm/vmware/xorg/vmw_ioctl.c +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_ioctl.c @@ -31,7 +31,9 @@ * @author Jakob Bornecrantz <[email protected]> */ -#define HAVE_STDINT_H +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H 1 +#endif #define _FILE_OFFSET_BITS 64 #include <errno.h> @@ -54,8 +56,108 @@ struct vmw_dma_buffer uint32_t size; }; +static int +vmw_ioctl_get_param(struct vmw_customizer *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_customizer *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_customizer *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_customizer *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_customizer *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_customizer *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) +vmw_ioctl_buffer_create(struct vmw_customizer *vmw, uint32_t size, unsigned *handle) { struct vmw_dma_buffer *buf; union drm_vmw_alloc_dmabuf_arg arg; @@ -96,7 +198,7 @@ err: } void -vmw_ioctl_buffer_destroy(struct vmw_driver *vmw, struct vmw_dma_buffer *buf) +vmw_ioctl_buffer_destroy(struct vmw_customizer *vmw, struct vmw_dma_buffer *buf) { struct drm_vmw_unref_dmabuf_arg arg; @@ -113,7 +215,7 @@ vmw_ioctl_buffer_destroy(struct vmw_driver *vmw, struct vmw_dma_buffer *buf) } void * -vmw_ioctl_buffer_map(struct vmw_driver *vmw, struct vmw_dma_buffer *buf) +vmw_ioctl_buffer_map(struct vmw_customizer *vmw, struct vmw_dma_buffer *buf) { void *map; @@ -134,7 +236,7 @@ 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) +vmw_ioctl_buffer_unmap(struct vmw_customizer *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 index 344ef0b3159..f43f91e5c0d 100644 --- a/src/gallium/winsys/drm/vmware/xorg/vmw_screen.c +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_screen.c @@ -33,41 +33,104 @@ #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_customizer *vmw = + vmw_customizer(xorg_customizer(crtc->scrn)); + 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(struct vmw_customizer *vmw) +{ + ScrnInfoPtr pScrn = vmw->pScrn; + 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(struct vmw_customizer *vmw) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(vmw->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) +vmw_screen_init(CustomizerPtr cust, int fd) { - modesettingPtr ms = modesettingPTR(pScrn); - struct vmw_driver *vmw; + struct vmw_customizer *vmw = vmw_customizer(cust); + + vmw->fd = fd; + vmw_screen_cursor_init(vmw); - /* if gallium is used then we don't need to do anything. */ - if (ms->screen) + /* if gallium is used then we don't need to do anything more. */ + if (xorg_has_gallium(vmw->pScrn)) return TRUE; - vmw = xnfcalloc(sizeof(*vmw), 1); + vmw_video_init(vmw); + + return TRUE; +} + +static Bool +vmw_screen_close(CustomizerPtr cust) +{ + struct vmw_customizer *vmw = vmw_customizer(cust); + if (!vmw) - return FALSE; + return TRUE; - vmw->fd = ms->fd; - ms->winsys_priv = vmw; + vmw_screen_cursor_close(vmw); - vmw_video_init(pScrn, vmw); + vmw_video_close(vmw); return TRUE; } static Bool -vmw_screen_close(ScrnInfoPtr pScrn) +vmw_screen_enter_vt(CustomizerPtr cust) { - modesettingPtr ms = modesettingPTR(pScrn); - struct vmw_driver *vmw = vmw_driver(pScrn); + debug_printf("%s: enter\n", __func__); - if (!vmw) - return TRUE; + return TRUE; +} - vmw_video_close(pScrn, vmw); +static Bool +vmw_screen_leave_vt(CustomizerPtr cust) +{ + struct vmw_customizer *vmw = vmw_customizer(cust); + + debug_printf("%s: enter\n", __func__); - ms->winsys_priv = NULL; - xfree(vmw); + vmw_video_stop_all(vmw); return TRUE; } @@ -81,16 +144,27 @@ static Bool (*vmw_screen_pre_init_saved)(ScrnInfoPtr pScrn, int flags) = NULL; static Bool vmw_screen_pre_init(ScrnInfoPtr pScrn, int flags) { - modesettingPtr ms; + struct vmw_customizer *vmw; + CustomizerPtr cust; + + vmw = xnfcalloc(1, sizeof(*vmw)); + if (!vmw) + return FALSE; + + cust = &vmw->base; + + cust->winsys_screen_init = vmw_screen_init; + cust->winsys_screen_close = vmw_screen_close; + cust->winsys_enter_vt = vmw_screen_enter_vt; + cust->winsys_leave_vt = vmw_screen_leave_vt; + vmw->pScrn = pScrn; + + pScrn->driverPrivate = cust; 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; - return TRUE; } diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_video.c b/src/gallium/winsys/drm/vmware/xorg/vmw_video.c index 6e34aa21f38..de28f06a475 100644 --- a/src/gallium/winsys/drm/vmware/xorg/vmw_video.c +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_video.c @@ -226,7 +226,7 @@ static void vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, /* * Local functions. */ -static XF86VideoAdaptorPtr vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_driver *vmw); +static XF86VideoAdaptorPtr vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_customizer *vmw); static int vmw_video_port_init(ScrnInfoPtr pScrn, struct vmw_video_port *port, @@ -243,9 +243,9 @@ static int vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, 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, +static int vmw_video_buffer_alloc(struct vmw_customizer *vmw, int size, struct vmw_video_buffer *out); -static int vmw_video_buffer_free(struct vmw_driver *vmw, +static int vmw_video_buffer_free(struct vmw_customizer *vmw, struct vmw_video_buffer *out); @@ -267,15 +267,27 @@ static int vmw_video_buffer_free(struct vmw_driver *vmw, */ Bool -vmw_video_init(ScrnInfoPtr pScrn, struct vmw_driver *vmw) +vmw_video_init(struct vmw_customizer *vmw) { + ScrnInfoPtr pScrn = vmw->pScrn; 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); @@ -334,17 +346,22 @@ vmw_video_init(ScrnInfoPtr pScrn, struct vmw_driver *vmw) */ Bool -vmw_video_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw) +vmw_video_close(struct vmw_customizer *vmw) { + ScrnInfoPtr pScrn = vmw->pScrn; 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) { - vmw_video_port_cleanup(pScrn, &video->port[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 */ @@ -359,6 +376,39 @@ vmw_video_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw) /* *----------------------------------------------------------------------------- * + * vmw_video_stop_all -- + * + * Stop all video streams from playing. + * + * Results: + * None. + * + * Side effects: + * All buffers are freed. + * + *----------------------------------------------------------------------------- + */ + +void vmw_video_stop_all(struct vmw_customizer *vmw) +{ + ScrnInfoPtr pScrn = vmw->pScrn; + 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 @@ -374,7 +424,7 @@ vmw_video_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw) */ static XF86VideoAdaptorPtr -vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_driver *vmw) +vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_customizer *vmw) { XF86VideoAdaptorPtr adaptor; struct vmw_video_private *video; @@ -408,7 +458,7 @@ vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_driver *vmw) adaptor->pPortPrivates = video->port_ptr; for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { - video->port[i].streamId = 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; @@ -468,7 +518,7 @@ vmw_video_port_init(ScrnInfoPtr pScrn, struct vmw_video_port *port, unsigned char *buf, short width, short height, RegionPtr clipBoxes) { - struct vmw_driver *vmw = vmw_driver(pScrn); + struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); unsigned short w, h; int i, ret; @@ -536,8 +586,8 @@ vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, unsigned char *buf, short width, short height, RegionPtr clipBoxes) { - struct vmw_driver *vmw = vmw_driver(pScrn); - struct drm_vmw_overlay_arg arg; + struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); + struct drm_vmw_control_stream_arg arg; unsigned short w, h; int size; int ret; @@ -596,13 +646,14 @@ vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, } } - ret = drmCommandWrite(vmw->fd, DRM_VMW_OVERLAY, &arg, sizeof(arg)); + 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); + if (++(port->currBuf) >= VMWARE_VID_NUM_BUFFERS) + port->currBuf = 0; return Success; } @@ -627,7 +678,7 @@ vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmw_video_port *port) { - struct vmw_driver *vmw = vmw_driver(pScrn); + struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); uint32 id, colorKey, flags; Bool isAutoPaintColorkey; int i; @@ -673,7 +724,7 @@ vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmw_video_port *port) */ static int -vmw_video_buffer_alloc(struct vmw_driver *vmw, int size, +vmw_video_buffer_alloc(struct vmw_customizer *vmw, int size, struct vmw_video_buffer *out) { out->buf = vmw_ioctl_buffer_create(vmw, size, &out->handle); @@ -716,7 +767,7 @@ vmw_video_buffer_alloc(struct vmw_driver *vmw, int size, */ static int -vmw_video_buffer_free(struct vmw_driver *vmw, +vmw_video_buffer_free(struct vmw_customizer *vmw, struct vmw_video_buffer *out) { if (out->size == 0) @@ -766,7 +817,7 @@ vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, Bool sync, RegionPtr clipBoxes, pointer data, DrawablePtr dst) { - struct vmw_driver *vmw = vmw_driver(pScrn); + struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); struct vmw_video_port *port = data; debug_printf("%s: enter (%u, %u) (%ux%u) (%u, %u) (%ux%u) (%ux%u)\n", __func__, @@ -804,9 +855,9 @@ vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, static void vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup) { - struct vmw_driver *vmw = vmw_driver(pScrn); + struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); struct vmw_video_port *port = data; - struct drm_vmw_overlay_arg arg; + struct drm_vmw_control_stream_arg arg; int ret; debug_printf("%s: cleanup is %s\n", __func__, cleanup ? "TRUE" : "FALSE"); @@ -822,7 +873,7 @@ vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup) arg.stream_id = port->streamId; arg.enabled = FALSE; - ret = drmCommandWrite(vmw->fd, DRM_VMW_OVERLAY, &arg, sizeof(arg)); + ret = drmCommandWrite(vmw->fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg)); assert(ret == 0); vmw_video_port_cleanup(pScrn, port); diff --git a/src/gallium/winsys/drm/vmware/xorg/vmw_xorg.c b/src/gallium/winsys/drm/vmware/xorg/vmw_xorg.c index 4b208719ca3..87aad25b24f 100644 --- a/src/gallium/winsys/drm/vmware/xorg/vmw_xorg.c +++ b/src/gallium/winsys/drm/vmware/xorg/vmw_xorg.c @@ -33,11 +33,49 @@ #include "vmw_hook.h" + +/* + * Defines and modinfo + */ + +#define VMWGFX_DRIVER_NAME "vmwgfx" + +#define VMW_STRING_INNER(s) #s +#define VMW_STRING(str) VMW_STRING_INNER(str) + +#define VMWGFX_VERSION_MAJOR 11 +#define VMWGFX_VERSION_MINOR 0 +#define VMWGFX_VERSION_PATCH 0 +#define VMWGFX_VERSION_STRING_MAJOR VMW_STRING(VMWGFX_VERSION_MAJOR) +#define VMWGFX_VERSION_STRING_MINOR VMW_STRING(VMWGFX_VERSION_MINOR) +#define VMWGFX_VERSION_STRING_PATCH VMW_STRING(VMWGFX_VERSION_PATCH) + +#define VMWGFX_DRIVER_VERSION \ + (VMWGFX_VERSION_MAJOR * 65536 + VMWGFX_VERSION_MINOR * 256 + VMWGFX_VERSION_PATCH) +#define VMWGFX_DRIVER_VERSION_STRING \ + VMWGFX_VERSION_STRING_MAJOR "." VMWGFX_VERSION_STRING_MINOR \ + "." VMWGFX_VERSION_STRING_PATCH + +/* + * Standard four digit version string expected by VMware Tools installer. + * As the driver's version is only {major, minor, patchlevel}, simply append an + * extra zero for the fourth digit. + */ +#ifdef __GNUC__ +_X_EXPORT const char vmwgfx_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = + "version=" VMWGFX_DRIVER_VERSION_STRING ".0"; +#endif + 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); +_X_EXPORT Bool vmw_xorg_pci_probe(DriverPtr driver, + int entity_num, + struct pci_device *device, + intptr_t match_data); + + +/* + * Tables + */ static const struct pci_id_match vmw_xorg_device_match[] = { {0x15ad, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0}, @@ -55,12 +93,12 @@ static PciChipsets vmw_xorg_pci_devices[] = { }; static XF86ModuleVersionInfo vmw_xorg_version = { - "vmwgfx", + VMWGFX_DRIVER_NAME, MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, XORG_VERSION_CURRENT, - 0, 1, 0, /* major, minor, patch */ + VMWGFX_VERSION_MAJOR, VMWGFX_VERSION_MINOR, VMWGFX_VERSION_PATCH, ABI_CLASS_VIDEODRV, ABI_VIDEODRV_VERSION, MOD_CLASS_VIDEODRV, @@ -73,7 +111,7 @@ static XF86ModuleVersionInfo vmw_xorg_version = { _X_EXPORT DriverRec vmwgfx = { 1, - "vmwgfx", + VMWGFX_DRIVER_NAME, vmw_xorg_identify, NULL, xorg_tracker_available_options, @@ -92,6 +130,7 @@ _X_EXPORT XF86ModuleData vmwgfxModuleData = { NULL }; + /* * Xorg driver functions */ @@ -126,7 +165,7 @@ vmw_xorg_identify(int flags) vmw_xorg_chipsets); } -static Bool +_X_EXPORT Bool vmw_xorg_pci_probe(DriverPtr driver, int entity_num, struct pci_device *device, intptr_t match_data) { |