diff options
Diffstat (limited to 'src/gallium/winsys')
45 files changed, 2254 insertions, 1254 deletions
diff --git a/src/gallium/winsys/drm/Makefile.template b/src/gallium/winsys/drm/Makefile.template index 985e5a861f..9635c3c50e 100644 --- a/src/gallium/winsys/drm/Makefile.template +++ b/src/gallium/winsys/drm/Makefile.template @@ -83,7 +83,9 @@ 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 $@ \ - $(OBJECTS) $(PIPE_DRIVERS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS) $(DRIVER_EXTRAS) + $(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) \ diff --git a/src/gallium/winsys/drm/intel/dri/SConscript b/src/gallium/winsys/drm/intel/dri/SConscript index e14e96e32f..f973811072 100644 --- a/src/gallium/winsys/drm/intel/dri/SConscript +++ b/src/gallium/winsys/drm/intel/dri/SConscript @@ -2,15 +2,19 @@ Import('*') env = drienv.Clone() +env.ParseConfig('pkg-config --cflags --libs libdrm_intel') + drivers = [ + st_dri, + inteldrm, softpipe, i915simple, trace, - inteldrm ] -env.SharedLibrary( +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 c5217ad2d6..490baded66 100644 --- a/src/gallium/winsys/drm/intel/egl/Makefile +++ b/src/gallium/winsys/drm/intel/egl/Makefile @@ -8,6 +8,7 @@ PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ $(GALLIUMDIR)/winsys/drm/intel/gem/libinteldrm.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/i915simple/libi915simple.a DRIVER_SOURCES = diff --git a/src/gallium/winsys/drm/intel/gem/Makefile b/src/gallium/winsys/drm/intel/gem/Makefile index 7ab1a2a771..0d6d4e37db 100644 --- a/src/gallium/winsys/drm/intel/gem/Makefile +++ b/src/gallium/winsys/drm/intel/gem/Makefile @@ -4,10 +4,10 @@ include $(TOP)/configs/current LIBNAME = inteldrm C_SOURCES = \ - intel_be_batchbuffer.c \ - intel_be_context.c \ - intel_be_device.c \ - intel_be_api.c + intel_drm_batchbuffer.c \ + intel_drm_buffer.c \ + intel_drm_fence.c \ + intel_drm_api.c LIBRARY_INCLUDES = $(shell pkg-config libdrm --cflags-only-I) diff --git a/src/gallium/winsys/drm/intel/gem/SConscript b/src/gallium/winsys/drm/intel/gem/SConscript index ea8a2e55f6..26717f391f 100644 --- a/src/gallium/winsys/drm/intel/gem/SConscript +++ b/src/gallium/winsys/drm/intel/gem/SConscript @@ -3,10 +3,10 @@ Import('*') env = drienv.Clone() inteldrm_sources = [ - 'intel_be_api.c', - 'intel_be_batchbuffer.c', - 'intel_be_context.c', - 'intel_be_device.c', + 'intel_drm_api.c', + 'intel_drm_batchbuffer.c', + 'intel_drm_buffer.c', + 'intel_drm_fence.c', ] inteldrm = env.ConvenienceLibrary( diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_api.c b/src/gallium/winsys/drm/intel/gem/intel_be_api.c deleted file mode 100644 index dd5f814da3..0000000000 --- a/src/gallium/winsys/drm/intel/gem/intel_be_api.c +++ /dev/null @@ -1,37 +0,0 @@ - -#include "intel_be_api.h" -#include "i915simple/i915_winsys.h" -#include "identity/id_drm.h" -#include "trace/tr_drm.h" - -static void destroy(struct drm_api *api) -{ - -} - -struct drm_api intel_be_drm_api = -{ - /* intel_be_context.c */ - .create_context = intel_be_create_context, - /* intel_be_device.c */ - .create_screen = intel_be_create_screen, - .buffer_from_texture = intel_be_get_texture_buffer, - .buffer_from_handle = intel_be_buffer_from_handle, - .handle_from_buffer = intel_be_handle_from_buffer, - .global_handle_from_buffer = intel_be_global_handle_from_buffer, - .destroy = destroy, -}; - -struct drm_api * -drm_api_create() -{ -#ifdef DEBUG -#if 0 - return identity_drm_create(&intel_be_drm_api); -#else - return trace_drm_create(&intel_be_drm_api); -#endif -#else - return &intel_be_drm_api; -#endif -} diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_api.h b/src/gallium/winsys/drm/intel/gem/intel_be_api.h deleted file mode 100644 index f286b62eb8..0000000000 --- a/src/gallium/winsys/drm/intel/gem/intel_be_api.h +++ /dev/null @@ -1,18 +0,0 @@ - -#ifndef _INTEL_BE_API_H_ -#define _INTEL_BE_API_H_ - -#include "pipe/p_compiler.h" - -#include "state_tracker/drm_api.h" - -#include "intel_be_device.h" - -extern struct drm_api intel_be_drm_api; - -struct pipe_screen *intel_be_create_screen(struct drm_api *api, int drmFD, - struct drm_create_screen_arg *arg); -struct pipe_context *intel_be_create_context(struct drm_api *api, - struct pipe_screen *screen); - -#endif diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c b/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c deleted file mode 100644 index d5e63c3bae..0000000000 --- a/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c +++ /dev/null @@ -1,139 +0,0 @@ - -#include "i915simple/i915_debug.h" -#include "intel_be_batchbuffer.h" -#include "intel_be_context.h" -#include "intel_be_device.h" -#include "intel_be_fence.h" -#include <errno.h> - -#include "util/u_memory.h" - -struct intel_be_batchbuffer * -intel_be_batchbuffer_alloc(struct intel_be_context *intel) -{ - struct intel_be_batchbuffer *batch = CALLOC_STRUCT(intel_be_batchbuffer); - - - batch->base.buffer = NULL; - batch->base.winsys = &intel->base; - batch->base.map = NULL; - batch->base.ptr = NULL; - batch->base.size = 0; - batch->base.actual_size = intel->device->max_batch_size; - batch->base.relocs = 0; - batch->base.max_relocs = 500;/*INTEL_DEFAULT_RELOCS;*/ - - batch->base.map = malloc(batch->base.actual_size); - memset(batch->base.map, 0, batch->base.actual_size); - - batch->base.ptr = batch->base.map; - - intel_be_batchbuffer_reset(batch); - - return batch; -} - -void -intel_be_batchbuffer_reset(struct intel_be_batchbuffer *batch) -{ - struct intel_be_context *intel = intel_be_context(batch->base.winsys); - struct intel_be_device *dev = intel->device; - - if (batch->bo) - drm_intel_bo_unreference(batch->bo); - - memset(batch->base.map, 0, batch->base.actual_size); - batch->base.ptr = batch->base.map; - batch->base.size = batch->base.actual_size - BATCH_RESERVED; - - batch->base.relocs = 0; - - batch->bo = drm_intel_bo_alloc(dev->pools.gem, - "gallium3d_batch_buffer", - batch->base.actual_size, 0); -} - -int -intel_be_offset_relocation(struct intel_be_batchbuffer *batch, - unsigned pre_add, - drm_intel_bo *bo, - uint32_t read_domains, - uint32_t write_domain) -{ - unsigned offset; - int ret = 0; - - assert(batch->base.relocs < batch->base.max_relocs); - - offset = (unsigned)(batch->base.ptr - batch->base.map); - - ret = drm_intel_bo_emit_reloc(batch->bo, offset, - bo, pre_add, - read_domains, - write_domain); - - ((uint32_t*)batch->base.ptr)[0] = bo->offset + pre_add; - batch->base.ptr += 4; - - if (!ret) - batch->base.relocs++; - - return ret; -} - -void -intel_be_batchbuffer_flush(struct intel_be_batchbuffer *batch, - struct intel_be_fence **fence) -{ - struct i915_batchbuffer *i915 = &batch->base; - unsigned used = 0; - int ret = 0; - - assert(i915_batchbuffer_space(i915) >= 0); - - used = batch->base.ptr - batch->base.map; - assert((used & 3) == 0); - - if (used & 4) { - i915_batchbuffer_dword(i915, (0x0<<29)|(0x4<<23)|(1<<0)); // MI_FLUSH | FLUSH_MAP_CACHE; - i915_batchbuffer_dword(i915, (0x0<<29)|(0x0<<23)); // MI_NOOP - i915_batchbuffer_dword(i915, (0x0<<29)|(0xA<<23)); // MI_BATCH_BUFFER_END; - } else { - i915_batchbuffer_dword(i915, (0x0<<29)|(0x4<<23)|(1<<0)); //MI_FLUSH | FLUSH_MAP_CACHE; - i915_batchbuffer_dword(i915, (0x0<<29)|(0xA<<23)); // MI_BATCH_BUFFER_END; - } - - used = batch->base.ptr - batch->base.map; - - drm_intel_bo_subdata(batch->bo, 0, used, batch->base.map); - ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0); - - assert(ret == 0); - - intel_be_batchbuffer_reset(batch); - - if (fence) { - if (*fence) - intel_be_fence_reference(fence, NULL); - - (*fence) = CALLOC_STRUCT(intel_be_fence); - pipe_reference_init(&(*fence)->reference, 1); - (*fence)->bo = NULL; - } -} - -void -intel_be_batchbuffer_finish(struct intel_be_batchbuffer *batch) -{ - -} - -void -intel_be_batchbuffer_free(struct intel_be_batchbuffer *batch) -{ - if (batch->bo) - drm_intel_bo_unreference(batch->bo); - - free(batch->base.map); - free(batch); -} diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.h b/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.h deleted file mode 100644 index 195bf8dee7..0000000000 --- a/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.h +++ /dev/null @@ -1,55 +0,0 @@ - -#ifndef INTEL_BE_BATCHBUFFER_H -#define INTEL_BE_BATCHBUFFER_H - -#include "i915simple/i915_batch.h" - -#include "drm.h" -#include "intel_bufmgr.h" - -#define BATCH_RESERVED 16 - -#define INTEL_DEFAULT_RELOCS 100 -#define INTEL_MAX_RELOCS 400 - -#define INTEL_BATCH_NO_CLIPRECTS 0x1 -#define INTEL_BATCH_CLIPRECTS 0x2 - -struct intel_be_context; -struct intel_be_device; -struct intel_be_fence; - -struct intel_be_batchbuffer -{ - struct i915_batchbuffer base; - - struct intel_be_context *intel; - struct intel_be_device *device; - - drm_intel_bo *bo; -}; - -struct intel_be_batchbuffer * -intel_be_batchbuffer_alloc(struct intel_be_context *intel); - -void -intel_be_batchbuffer_free(struct intel_be_batchbuffer *batch); - -void -intel_be_batchbuffer_finish(struct intel_be_batchbuffer *batch); - -void -intel_be_batchbuffer_flush(struct intel_be_batchbuffer *batch, - struct intel_be_fence **fence); - -void -intel_be_batchbuffer_reset(struct intel_be_batchbuffer *batch); - -int -intel_be_offset_relocation(struct intel_be_batchbuffer *batch, - unsigned pre_add, - drm_intel_bo *bo, - uint32_t read_domains, - uint32_t write_doman); - -#endif diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_context.c b/src/gallium/winsys/drm/intel/gem/intel_be_context.c deleted file mode 100644 index db84f9af51..0000000000 --- a/src/gallium/winsys/drm/intel/gem/intel_be_context.c +++ /dev/null @@ -1,120 +0,0 @@ - -#include "pipe/p_screen.h" - -#include "softpipe/sp_winsys.h" - -#include "intel_be_device.h" -#include "intel_be_context.h" -#include "intel_be_batchbuffer.h" - -#include "i915_drm.h" - -#include "intel_be_api.h" - -static struct i915_batchbuffer * -intel_be_batch_get(struct i915_winsys *sws) -{ - struct intel_be_context *intel = intel_be_context(sws); - return &intel->batch->base; -} - -static void -intel_be_batch_reloc(struct i915_winsys *sws, - struct pipe_buffer *buf, - unsigned access_flags, - unsigned delta) -{ - struct intel_be_context *intel = intel_be_context(sws); - drm_intel_bo *bo = intel_bo(buf); - int ret; - uint32_t read = 0; - uint32_t write = 0; - - if (access_flags & I915_BUFFER_ACCESS_WRITE) { - write = I915_GEM_DOMAIN_RENDER; - read = I915_GEM_DOMAIN_RENDER; - } - - if (access_flags & I915_BUFFER_ACCESS_READ) { - read |= I915_GEM_DOMAIN_VERTEX; - } - - ret = intel_be_offset_relocation(intel->batch, - delta, - bo, - read, - write); - assert(ret == 0); - - /* TODO change return type */ - /* return ret; */ -} - -static void -intel_be_batch_flush(struct i915_winsys *sws, - struct pipe_fence_handle **fence) -{ - struct intel_be_context *intel = intel_be_context(sws); - struct intel_be_fence **f = (struct intel_be_fence **)fence; - - if (fence && *fence) - assert(0); - - intel_be_batchbuffer_flush(intel->batch, f); -} - - -/* - * Misc functions. - */ - -static void -intel_be_destroy_context(struct i915_winsys *winsys) -{ - struct intel_be_context *intel = intel_be_context(winsys); - - intel_be_batchbuffer_free(intel->batch); - - free(intel); -} - -boolean -intel_be_init_context(struct intel_be_context *intel, struct intel_be_device *device) -{ - assert(intel); - assert(device); - intel->device = device; - - intel->base.batch_get = intel_be_batch_get; - intel->base.batch_reloc = intel_be_batch_reloc; - intel->base.batch_flush = intel_be_batch_flush; - - intel->base.destroy = intel_be_destroy_context; - - intel->batch = intel_be_batchbuffer_alloc(intel); - - return true; -} - -struct pipe_context * -intel_be_create_context(struct drm_api *api, struct pipe_screen *screen) -{ - struct intel_be_context *intel; - struct pipe_context *pipe; - struct intel_be_device *device = intel_be_device(screen->winsys); - - intel = (struct intel_be_context *)malloc(sizeof(*intel)); - memset(intel, 0, sizeof(*intel)); - - intel_be_init_context(intel, device); - - if (device->softpipe) - pipe = softpipe_create(screen); - else - pipe = i915_create_context(screen, &device->base, &intel->base); - - if (pipe) - pipe->priv = intel; - - return pipe; -} diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_context.h b/src/gallium/winsys/drm/intel/gem/intel_be_context.h deleted file mode 100644 index 5a369669c0..0000000000 --- a/src/gallium/winsys/drm/intel/gem/intel_be_context.h +++ /dev/null @@ -1,31 +0,0 @@ - -#ifndef INTEL_BE_CONTEXT_H -#define INTEL_BE_CONTEXT_H - -#include "i915simple/i915_winsys.h" - -struct intel_be_context -{ - /** Interface to i915simple driver */ - struct i915_winsys base; - - struct intel_be_device *device; - struct intel_be_batchbuffer *batch; -}; - -static INLINE struct intel_be_context * -intel_be_context(struct i915_winsys *sws) -{ - return (struct intel_be_context *)sws; -} - -/** - * Intialize a allocated intel_be_context struct. - * - * Remember to set the hardware_* functions. - */ -boolean -intel_be_init_context(struct intel_be_context *intel, - struct intel_be_device *device); - -#endif diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_device.c b/src/gallium/winsys/drm/intel/gem/intel_be_device.c deleted file mode 100644 index e3630f5d12..0000000000 --- a/src/gallium/winsys/drm/intel/gem/intel_be_device.c +++ /dev/null @@ -1,369 +0,0 @@ - -#include "intel_be_device.h" - -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "pipe/p_inlines.h" -#include "util/u_memory.h" -#include "util/u_debug.h" - -#include "intel_be_fence.h" - -#include "i915simple/i915_winsys.h" -#include "softpipe/sp_winsys.h" - -#include "intel_be_api.h" -#include <stdio.h> - -/* - * Buffer - */ - -static void * -intel_be_buffer_map(struct pipe_winsys *winsys, - struct pipe_buffer *buf, - unsigned flags) -{ - drm_intel_bo *bo = intel_bo(buf); - int write = 0; - int ret; - - if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { - /* Remove this when drm_intel_bo_map supports DONTBLOCK - */ - return NULL; - } - - if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) - write = 1; - - ret = drm_intel_bo_map(bo, write); - - if (ret) - return NULL; - - return bo->virtual; -} - -static void -intel_be_buffer_unmap(struct pipe_winsys *winsys, - struct pipe_buffer *buf) -{ - drm_intel_bo_unmap(intel_bo(buf)); -} - -static void -intel_be_buffer_destroy(struct pipe_buffer *buf) -{ - drm_intel_bo_unreference(intel_bo(buf)); - free(buf); -} - -static struct pipe_buffer * -intel_be_buffer_create(struct pipe_winsys *winsys, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct intel_be_buffer *buffer = CALLOC_STRUCT(intel_be_buffer); - struct intel_be_device *dev = intel_be_device(winsys); - drm_intel_bufmgr *pool; - char *name; - - if (!buffer) - return NULL; - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - buffer->flinked = FALSE; - buffer->flink = 0; - - if (usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_CONSTANT)) { - /* Local buffer */ - name = "gallium3d_local"; - pool = dev->pools.gem; - } else if (usage & PIPE_BUFFER_USAGE_CUSTOM) { - /* For vertex buffers */ - name = "gallium3d_internal_vertex"; - pool = dev->pools.gem; - } else { - /* Regular buffers */ - name = "gallium3d_regular"; - pool = dev->pools.gem; - } - - buffer->bo = drm_intel_bo_alloc(pool, name, size, alignment); - - if (!buffer->bo) - goto err; - - return &buffer->base; - -err: - free(buffer); - return NULL; -} - -static struct pipe_buffer * -intel_be_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes) -{ - struct intel_be_buffer *buffer = CALLOC_STRUCT(intel_be_buffer); - struct intel_be_device *dev = intel_be_device(winsys); - int ret; - - if (!buffer) - return NULL; - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = 0; - buffer->base.usage = 0; - buffer->base.size = bytes; - - buffer->bo = drm_intel_bo_alloc(dev->pools.gem, - "gallium3d_user_buffer", - bytes, 0); - - if (!buffer->bo) - goto err; - - ret = drm_intel_bo_subdata(buffer->bo, - 0, bytes, ptr); - - if (ret) - goto err; - - return &buffer->base; - -err: - free(buffer); - return NULL; -} - -boolean -intel_be_get_texture_buffer(struct drm_api *api, - struct pipe_texture *texture, - struct pipe_buffer **buffer, - unsigned *stride) -{ - struct intel_be_device *dev; - - if (!texture) - return FALSE; - - dev = intel_be_device(texture->screen->winsys); - if (dev->softpipe) - return softpipe_get_texture_buffer(texture, buffer, stride); - else - return i915_get_texture_buffer(texture, buffer, stride); -} - -struct pipe_buffer * -intel_be_buffer_from_handle(struct drm_api *api, - struct pipe_screen *screen, - const char* name, unsigned handle) -{ - struct intel_be_device *dev = intel_be_device(screen->winsys); - struct intel_be_buffer *buffer = CALLOC_STRUCT(intel_be_buffer); - - if (!buffer) - return NULL; - - buffer->bo = drm_intel_bo_gem_create_from_name(dev->pools.gem, name, handle); - - if (!buffer->bo) - goto err; - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.screen = screen; - buffer->base.alignment = buffer->bo->align; - buffer->base.usage = PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE | - PIPE_BUFFER_USAGE_CPU_READ | - PIPE_BUFFER_USAGE_CPU_WRITE; - buffer->base.size = buffer->bo->size; - - return &buffer->base; - -err: - free(buffer); - return NULL; -} - -boolean -intel_be_handle_from_buffer(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_buffer *buffer, - unsigned *handle) -{ - if (!buffer) - return FALSE; - - *handle = intel_bo(buffer)->handle; - return TRUE; -} - -boolean -intel_be_global_handle_from_buffer(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_buffer *buffer, - unsigned *handle) -{ - struct intel_be_buffer *buf = intel_be_buffer(buffer); - - if (!buffer) - return FALSE; - - if (!buf->flinked) { - if (drm_intel_bo_flink(intel_bo(buffer), &buf->flink)) - return FALSE; - buf->flinked = TRUE; - } - - *handle = buf->flink; - return TRUE; -} -/* - * Fence - */ - -static void -intel_be_fence_refunref(struct pipe_winsys *sws, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ - struct intel_be_fence **p = (struct intel_be_fence **)ptr; - struct intel_be_fence *f = (struct intel_be_fence *)fence; - - intel_be_fence_reference(p, f); -} - -static int -intel_be_fence_signalled(struct pipe_winsys *sws, - struct pipe_fence_handle *fence, - unsigned flag) -{ - assert(0); - - return 0; -} - -static int -intel_be_fence_finish(struct pipe_winsys *sws, - struct pipe_fence_handle *fence, - unsigned flag) -{ - struct intel_be_fence *f = (struct intel_be_fence *)fence; - - /* fence already expired */ - if (!f->bo) - return 0; - - drm_intel_bo_wait_rendering(f->bo); - drm_intel_bo_unreference(f->bo); - f->bo = NULL; - - return 0; -} - -/* - * Misc functions - */ - -static void -intel_be_destroy_winsys(struct pipe_winsys *winsys) -{ - struct intel_be_device *dev = intel_be_device(winsys); - - drm_intel_bufmgr_destroy(dev->pools.gem); - - free(dev); -} - -boolean -intel_be_init_device(struct intel_be_device *dev, int fd, unsigned id) -{ - dev->fd = fd; - dev->id = id; - dev->max_batch_size = 16 * 4096; - dev->max_vertex_size = 128 * 4096; - - dev->base.buffer_create = intel_be_buffer_create; - dev->base.user_buffer_create = intel_be_user_buffer_create; - dev->base.buffer_map = intel_be_buffer_map; - dev->base.buffer_unmap = intel_be_buffer_unmap; - dev->base.buffer_destroy = intel_be_buffer_destroy; - - /* Not used anymore */ - dev->base.surface_buffer_create = NULL; - - dev->base.fence_reference = intel_be_fence_refunref; - dev->base.fence_signalled = intel_be_fence_signalled; - dev->base.fence_finish = intel_be_fence_finish; - - dev->base.destroy = intel_be_destroy_winsys; - - dev->pools.gem = drm_intel_bufmgr_gem_init(dev->fd, dev->max_batch_size); - - dev->softpipe = debug_get_bool_option("INTEL_SOFTPIPE", FALSE); - - return true; -} - -static void -intel_be_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); -} - -struct pipe_screen * -intel_be_create_screen(struct drm_api *api, int drmFD, - struct drm_create_screen_arg *arg) -{ - struct intel_be_device *dev; - struct pipe_screen *screen; - unsigned int deviceID; - - if (arg != NULL) { - switch(arg->mode) { - case DRM_CREATE_NORMAL: - break; - default: - return NULL; - } - } - - /* Allocate the private area */ - dev = malloc(sizeof(*dev)); - if (!dev) - return NULL; - memset(dev, 0, sizeof(*dev)); - - intel_be_get_device_id(&deviceID); - intel_be_init_device(dev, drmFD, deviceID); - - if (dev->softpipe) { - screen = softpipe_create_screen(&dev->base); - } else - screen = i915_create_screen(&dev->base, deviceID); - - return screen; -} diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_device.h b/src/gallium/winsys/drm/intel/gem/intel_be_device.h deleted file mode 100644 index 56d95bd7fe..0000000000 --- a/src/gallium/winsys/drm/intel/gem/intel_be_device.h +++ /dev/null @@ -1,108 +0,0 @@ - -#ifndef INTEL_DRM_DEVICE_H -#define INTEL_DRM_DEVICE_H - -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_context.h" - -#include "drm.h" -#include "intel_bufmgr.h" - -struct drm_api; - -/* - * Device - */ - -struct intel_be_device -{ - struct pipe_winsys base; - - boolean softpipe; - - int fd; /**< Drm file discriptor */ - - unsigned id; - - size_t max_batch_size; - size_t max_vertex_size; - - struct { - drm_intel_bufmgr *gem; - } pools; -}; - -static INLINE struct intel_be_device * -intel_be_device(struct pipe_winsys *winsys) -{ - return (struct intel_be_device *)winsys; -} - -boolean -intel_be_init_device(struct intel_be_device *device, int fd, unsigned id); - -/* - * Buffer - */ - -struct intel_be_buffer { - struct pipe_buffer base; - drm_intel_bo *bo; - boolean flinked; - unsigned flink; -}; - -/* - * Wrapper for driver get_texture_buffer functions. - */ -boolean -intel_be_get_texture_buffer(struct drm_api *api, - struct pipe_texture *texture, - struct pipe_buffer **buffer, - unsigned *stride); - -/** - * Create a be buffer from a drm bo handle. - * - * Takes a reference. - */ -struct pipe_buffer * -intel_be_buffer_from_handle(struct drm_api *api, - struct pipe_screen *screen, - const char* name, unsigned handle); - -/** - * Gets a handle from a buffer. - * - * If buffer is destroyed handle may become invalid. - */ -boolean -intel_be_handle_from_buffer(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_buffer *buffer, - unsigned *handle); - -/** - * Gets the global handle from a buffer. - * - * If buffer is destroyed handle may become invalid. - */ -boolean -intel_be_global_handle_from_buffer(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_buffer *buffer, - unsigned *handle); - -static INLINE struct intel_be_buffer * -intel_be_buffer(struct pipe_buffer *buf) -{ - return (struct intel_be_buffer *)buf; -} - -static INLINE drm_intel_bo * -intel_bo(struct pipe_buffer *buf) -{ - return intel_be_buffer(buf)->bo; -} - -#endif diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_fence.h b/src/gallium/winsys/drm/intel/gem/intel_be_fence.h deleted file mode 100644 index a8abb01a9e..0000000000 --- a/src/gallium/winsys/drm/intel/gem/intel_be_fence.h +++ /dev/null @@ -1,34 +0,0 @@ - -#ifndef INTEL_BE_FENCE_H -#define INTEL_BE_FENCE_H - -#include "pipe/p_defines.h" - -#include "drm.h" -#include "intel_bufmgr.h" - -/** - * Because gem does not have fence's we have to create our own fences. - * - * They work by keeping the batchbuffer around and checking if that has - * been idled. If bo is NULL fence has expired. - */ -struct intel_be_fence -{ - struct pipe_reference reference; - drm_intel_bo *bo; -}; - -static INLINE void -intel_be_fence_reference(struct intel_be_fence **ptr, struct intel_be_fence *f) -{ - struct intel_be_fence *old_fence = *ptr; - - if (pipe_reference((struct pipe_reference**)ptr, &f->reference)) { - if (old_fence->bo) - drm_intel_bo_unreference(old_fence->bo); - free(old_fence); - } -} - -#endif diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_api.c b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c new file mode 100644 index 0000000000..0fd5cdd969 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c @@ -0,0 +1,203 @@ + +#include "state_tracker/drm_api.h" + +#include "intel_drm_winsys.h" +#include "util/u_memory.h" + +#include "i915simple/i915_context.h" +#include "i915simple/i915_screen.h" + +#include "trace/tr_drm.h" + +/* + * Helper functions + */ + + +static void +intel_drm_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 intel_buffer * +intel_drm_buffer_from_handle(struct intel_drm_winsys *idws, + const char* name, unsigned handle) +{ + struct intel_drm_buffer *buf = CALLOC_STRUCT(intel_drm_buffer); + + if (!buf) + return NULL; + + buf->magic = 0xDEAD1337; + buf->bo = drm_intel_bo_gem_create_from_name(idws->pools.gem, name, handle); + buf->flinked = TRUE; + buf->flink = handle; + + if (!buf->bo) + goto err; + + return (struct intel_buffer *)buf; + +err: + FREE(buf); + return NULL; +} + + +/* + * Exported functions + */ + + +static struct pipe_texture * +intel_drm_texture_from_shared_handle(struct drm_api *api, + struct pipe_screen *screen, + struct pipe_texture *templ, + const char* name, + unsigned pitch, + unsigned handle) +{ + struct intel_drm_winsys *idws = intel_drm_winsys(i915_screen(screen)->iws); + struct intel_buffer *buffer; + + buffer = intel_drm_buffer_from_handle(idws, name, handle); + if (!buffer) + return NULL; + + return i915_texture_blanket_intel(screen, templ, pitch, buffer); +} + +static boolean +intel_drm_shared_handle_from_texture(struct drm_api *api, + struct pipe_screen *screen, + struct pipe_texture *texture, + unsigned *pitch, + unsigned *handle) +{ + struct intel_drm_buffer *buf = NULL; + struct intel_buffer *buffer = NULL; + if (!i915_get_texture_buffer_intel(texture, &buffer, pitch)) + return FALSE; + + buf = intel_drm_buffer(buffer); + if (!buf->flinked) { + if (drm_intel_bo_flink(buf->bo, &buf->flink)) + return FALSE; + buf->flinked = TRUE; + } + + *handle = buf->flink; + + return TRUE; +} + +static boolean +intel_drm_local_handle_from_texture(struct drm_api *api, + struct pipe_screen *screen, + struct pipe_texture *texture, + unsigned *pitch, + unsigned *handle) +{ + struct intel_buffer *buffer = NULL; + if (!i915_get_texture_buffer_intel(texture, &buffer, pitch)) + return FALSE; + + *handle = intel_drm_buffer(buffer)->bo->handle; + + return TRUE; +} + +static void +intel_drm_winsys_destroy(struct intel_winsys *iws) +{ + struct intel_drm_winsys *idws = intel_drm_winsys(iws); + + drm_intel_bufmgr_destroy(idws->pools.gem); + + FREE(idws); +} + +static struct pipe_screen * +intel_drm_create_screen(struct drm_api *api, int drmFD, + struct drm_create_screen_arg *arg) +{ + struct intel_drm_winsys *idws; + unsigned int deviceID; + + if (arg != NULL) { + switch(arg->mode) { + case DRM_CREATE_NORMAL: + break; + default: + return NULL; + } + } + + idws = CALLOC_STRUCT(intel_drm_winsys); + if (!idws) + return NULL; + + intel_drm_get_device_id(&deviceID); + + intel_drm_winsys_init_batchbuffer_functions(idws); + intel_drm_winsys_init_buffer_functions(idws); + intel_drm_winsys_init_fence_functions(idws); + + idws->fd = drmFD; + idws->id = deviceID; + idws->max_batch_size = 16 * 4096; + + idws->base.destroy = intel_drm_winsys_destroy; + + idws->pools.gem = drm_intel_bufmgr_gem_init(idws->fd, idws->max_batch_size); + + 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) +{ + +} + +struct drm_api intel_drm_api = +{ + .create_context = intel_drm_create_context, + .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, + .local_handle_from_texture = intel_drm_local_handle_from_texture, + .destroy = destroy, +}; + +struct drm_api * +drm_api_create() +{ + return trace_drm_create(&intel_drm_api); +} diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_batchbuffer.c b/src/gallium/winsys/drm/intel/gem/intel_drm_batchbuffer.c new file mode 100644 index 0000000000..ebd1b607b7 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_batchbuffer.c @@ -0,0 +1,229 @@ + +#include "intel_drm_winsys.h" +#include "util/u_memory.h" + +#include "i915_drm.h" + +#define BATCH_RESERVED 16 + +#define INTEL_DEFAULT_RELOCS 100 +#define INTEL_MAX_RELOCS 400 + +#define INTEL_BATCH_NO_CLIPRECTS 0x1 +#define INTEL_BATCH_CLIPRECTS 0x2 + +#undef INTEL_RUN_SYNC +#undef INTEL_MAP_BATCHBUFFER + +struct intel_drm_batchbuffer +{ + struct intel_batchbuffer base; + + size_t actual_size; + + drm_intel_bo *bo; +}; + +static INLINE struct intel_drm_batchbuffer * +intel_drm_batchbuffer(struct intel_batchbuffer *batch) +{ + return (struct intel_drm_batchbuffer *)batch; +} + +static void +intel_drm_batchbuffer_reset(struct intel_drm_batchbuffer *batch) +{ + struct intel_drm_winsys *idws = intel_drm_winsys(batch->base.iws); + + if (batch->bo) + drm_intel_bo_unreference(batch->bo); + batch->bo = drm_intel_bo_alloc(idws->pools.gem, + "gallium3d_batchbuffer", + batch->actual_size, + 4096); + +#ifdef INTEL_MAP_BATCHBUFFER + drm_intel_bo_map(batch->bo, TRUE); + batch->base.map = batch->bo->virtual; +#endif + + memset(batch->base.map, 0, batch->actual_size); + batch->base.ptr = batch->base.map; + batch->base.size = batch->actual_size - BATCH_RESERVED; + batch->base.relocs = 0; +} + +static struct intel_batchbuffer * +intel_drm_batchbuffer_create(struct intel_winsys *iws) +{ + struct intel_drm_winsys *idws = intel_drm_winsys(iws); + struct intel_drm_batchbuffer *batch = CALLOC_STRUCT(intel_drm_batchbuffer); + + batch->actual_size = idws->max_batch_size; + +#ifdef INTEL_MAP_BATCHBUFFER + batch->base.map = NULL; +#else + batch->base.map = MALLOC(batch->actual_size); +#endif + batch->base.ptr = NULL; + batch->base.size = 0; + + batch->base.relocs = 0; + batch->base.max_relocs = 300;/*INTEL_DEFAULT_RELOCS;*/ + + batch->base.iws = iws; + + intel_drm_batchbuffer_reset(batch); + + return &batch->base; +} + +static int +intel_drm_batchbuffer_reloc(struct intel_batchbuffer *ibatch, + struct intel_buffer *buffer, + enum intel_buffer_usage usage, + unsigned pre_add) +{ + struct intel_drm_batchbuffer *batch = intel_drm_batchbuffer(ibatch); + unsigned write_domain = 0; + unsigned read_domain = 0; + unsigned offset; + int ret = 0; + + assert(batch->base.relocs < batch->base.max_relocs); + + if (usage == INTEL_USAGE_SAMPLER) { + write_domain = 0; + read_domain = I915_GEM_DOMAIN_SAMPLER; + + } else if (usage == INTEL_USAGE_RENDER) { + write_domain = I915_GEM_DOMAIN_RENDER; + read_domain = I915_GEM_DOMAIN_RENDER; + + } else if (usage == INTEL_USAGE_2D_TARGET) { + write_domain = I915_GEM_DOMAIN_RENDER; + read_domain = I915_GEM_DOMAIN_RENDER; + + } else if (usage == INTEL_USAGE_2D_SOURCE) { + write_domain = 0; + read_domain = I915_GEM_DOMAIN_RENDER; + + } else if (usage == INTEL_USAGE_VERTEX) { + write_domain = 0; + read_domain = I915_GEM_DOMAIN_VERTEX; + + } else { + assert(0); + return -1; + } + + offset = (unsigned)(batch->base.ptr - batch->base.map); + + ret = drm_intel_bo_emit_reloc(batch->bo, offset, + intel_bo(buffer), pre_add, + read_domain, + write_domain); + + ((uint32_t*)batch->base.ptr)[0] = intel_bo(buffer)->offset + pre_add; + batch->base.ptr += 4; + + if (!ret) + batch->base.relocs++; + + return ret; +} + +static void +intel_drm_batchbuffer_flush(struct intel_batchbuffer *ibatch, + struct pipe_fence_handle **fence) +{ + struct intel_drm_batchbuffer *batch = intel_drm_batchbuffer(ibatch); + unsigned used = 0; + int ret = 0; + int i; + + assert(intel_batchbuffer_space(ibatch) >= 0); + + used = batch->base.ptr - batch->base.map; + assert((used & 3) == 0); + + if (used & 4) { + // MI_FLUSH | FLUSH_MAP_CACHE; + intel_batchbuffer_dword(ibatch, (0x0<<29)|(0x4<<23)|(1<<0)); + // MI_NOOP + intel_batchbuffer_dword(ibatch, (0x0<<29)|(0x0<<23)); + // MI_BATCH_BUFFER_END; + intel_batchbuffer_dword(ibatch, (0x0<<29)|(0xA<<23)); + } else { + //MI_FLUSH | FLUSH_MAP_CACHE; + intel_batchbuffer_dword(ibatch, (0x0<<29)|(0x4<<23)|(1<<0)); + // MI_BATCH_BUFFER_END; + intel_batchbuffer_dword(ibatch, (0x0<<29)|(0xA<<23)); + } + + used = batch->base.ptr - batch->base.map; + +#ifdef INTEL_MAP_BATCHBUFFER + drm_intel_bo_unmap(batch->bo); +#else + drm_intel_bo_subdata(batch->bo, 0, used, batch->base.map); +#endif + + /* Do the sending to HW */ + ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0); + assert(ret == 0); + + if (intel_drm_winsys(ibatch->iws)->dump_cmd) { + unsigned *ptr; + drm_intel_bo_map(batch->bo, FALSE); + ptr = (unsigned*)batch->bo->virtual; + + debug_printf("%s:\n", __func__); + for (i = 0; i < used / 4; i++, ptr++) { + debug_printf("\t%08x: %08x\n", i*4, *ptr); + } + + drm_intel_bo_unmap(batch->bo); + } else { +#ifdef INTEL_RUN_SYNC + drm_intel_bo_map(batch->bo, FALSE); + drm_intel_bo_unmap(batch->bo); +#endif + } + + if (fence) { + ibatch->iws->fence_reference(ibatch->iws, fence, NULL); + +#ifdef INTEL_RUN_SYNC + /* we run synced to GPU so just pass null */ + (*fence) = intel_drm_fence_create(NULL); +#else + (*fence) = intel_drm_fence_create(batch->bo); +#endif + } + + intel_drm_batchbuffer_reset(batch); +} + +static void +intel_drm_batchbuffer_destroy(struct intel_batchbuffer *ibatch) +{ + struct intel_drm_batchbuffer *batch = intel_drm_batchbuffer(ibatch); + + if (batch->bo) + drm_intel_bo_unreference(batch->bo); + +#ifndef INTEL_MAP_BATCHBUFFER + FREE(batch->base.map); +#endif + FREE(batch); +} + +void intel_drm_winsys_init_batchbuffer_functions(struct intel_drm_winsys *idws) +{ + idws->base.batchbuffer_create = intel_drm_batchbuffer_create; + idws->base.batchbuffer_reloc = intel_drm_batchbuffer_reloc; + idws->base.batchbuffer_flush = intel_drm_batchbuffer_flush; + idws->base.batchbuffer_destroy = intel_drm_batchbuffer_destroy; +} diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_buffer.c b/src/gallium/winsys/drm/intel/gem/intel_drm_buffer.c new file mode 100644 index 0000000000..0030f915a3 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_buffer.c @@ -0,0 +1,148 @@ + +#include "intel_drm_winsys.h" +#include "util/u_memory.h" + +#include "i915_drm.h" + +static struct intel_buffer * +intel_drm_buffer_create(struct intel_winsys *iws, + unsigned size, unsigned alignment, + enum intel_buffer_type type) +{ + struct intel_drm_buffer *buf = CALLOC_STRUCT(intel_drm_buffer); + struct intel_drm_winsys *idws = intel_drm_winsys(iws); + drm_intel_bufmgr *pool; + char *name; + + if (!buf) + return NULL; + + buf->magic = 0xDEAD1337; + buf->flinked = FALSE; + buf->flink = 0; + buf->map_gtt = FALSE; + + if (type == INTEL_NEW_TEXTURE) { + name = "gallium3d_texture"; + pool = idws->pools.gem; + } else if (type == INTEL_NEW_VERTEX) { + name = "gallium3d_vertex"; + pool = idws->pools.gem; + buf->map_gtt = TRUE; + } else if (type == INTEL_NEW_SCANOUT) { + name = "gallium3d_scanout"; + pool = idws->pools.gem; + buf->map_gtt = TRUE; + } else { + assert(0); + name = "gallium3d_unknown"; + pool = idws->pools.gem; + } + + buf->bo = drm_intel_bo_alloc(pool, name, size, alignment); + + if (!buf->bo) + goto err; + + return (struct intel_buffer *)buf; + +err: + assert(0); + FREE(buf); + return NULL; +} + +static int +intel_drm_buffer_set_fence_reg(struct intel_winsys *iws, + struct intel_buffer *buffer, + unsigned stride, + enum intel_buffer_tile tile) +{ + assert(I915_TILING_NONE == INTEL_TILE_NONE); + assert(I915_TILING_X == INTEL_TILE_X); + assert(I915_TILING_Y == INTEL_TILE_Y); + + return drm_intel_bo_set_tiling(intel_bo(buffer), &tile, stride); +} + +static void * +intel_drm_buffer_map(struct intel_winsys *iws, + struct intel_buffer *buffer, + boolean write) +{ + struct intel_drm_buffer *buf = intel_drm_buffer(buffer); + drm_intel_bo *bo = intel_bo(buffer); + int ret = 0; + + assert(bo); + + if (buf->map_count) + goto out; + + if (buf->map_gtt) + ret = drm_intel_gem_bo_map_gtt(bo); + else + ret = drm_intel_bo_map(bo, write); + + buf->ptr = bo->virtual; + + assert(ret == 0); +out: + if (ret) + return NULL; + + buf->map_count++; + return buf->ptr; +} + +static void +intel_drm_buffer_unmap(struct intel_winsys *iws, + struct intel_buffer *buffer) +{ + struct intel_drm_buffer *buf = intel_drm_buffer(buffer); + + if (--buf->map_count) + return; + + if (buf->map_gtt) + drm_intel_gem_bo_unmap_gtt(intel_bo(buffer)); + else + drm_intel_bo_unmap(intel_bo(buffer)); +} + +static int +intel_drm_buffer_write(struct intel_winsys *iws, + struct intel_buffer *buffer, + const void *data, + size_t size, + size_t offset) +{ + struct intel_drm_buffer *buf = intel_drm_buffer(buffer); + + return drm_intel_bo_subdata(buf->bo, offset, size, (void*)data); +} + +static void +intel_drm_buffer_destroy(struct intel_winsys *iws, + struct intel_buffer *buffer) +{ + drm_intel_bo_unreference(intel_bo(buffer)); + +#ifdef DEBUG + intel_drm_buffer(buffer)->magic = 0; + intel_drm_buffer(buffer)->bo = NULL; +#endif + + FREE(buffer); +} + +void +intel_drm_winsys_init_buffer_functions(struct intel_drm_winsys *idws) +{ + idws->base.buffer_create = intel_drm_buffer_create; + idws->base.buffer_set_fence_reg = intel_drm_buffer_set_fence_reg; + idws->base.buffer_map = intel_drm_buffer_map; + idws->base.buffer_unmap = intel_drm_buffer_unmap; + idws->base.buffer_write = intel_drm_buffer_write; + idws->base.buffer_destroy = intel_drm_buffer_destroy; +} diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c b/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c new file mode 100644 index 0000000000..e70bfe7b44 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c @@ -0,0 +1,81 @@ + +#include "intel_drm_winsys.h" +#include "util/u_memory.h" +#include "pipe/p_refcnt.h" + +/** + * Because gem does not have fence's we have to create our own fences. + * + * They work by keeping the batchbuffer around and checking if that has + * been idled. If bo is NULL fence has expired. + */ +struct intel_drm_fence +{ + struct pipe_reference reference; + drm_intel_bo *bo; +}; + + +struct pipe_fence_handle * +intel_drm_fence_create(drm_intel_bo *bo) +{ + struct intel_drm_fence *fence = CALLOC_STRUCT(intel_drm_fence); + + pipe_reference_init(&fence->reference, 1); + /* bo is null if fence already expired */ + if (bo) { + drm_intel_bo_reference(bo); + fence->bo = bo; + } + + return (struct pipe_fence_handle *)fence; +} + +static void +intel_drm_fence_reference(struct intel_winsys *iws, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + 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 (old->bo) + drm_intel_bo_unreference(old->bo); + FREE(old); + } +} + +static int +intel_drm_fence_signalled(struct intel_winsys *iws, + struct pipe_fence_handle *fence) +{ + assert(0); + + return 0; +} + +static int +intel_drm_fence_finish(struct intel_winsys *iws, + struct pipe_fence_handle *fence) +{ + struct intel_drm_fence *f = (struct intel_drm_fence *)fence; + + /* fence already expired */ + if (!f->bo) + return 0; + + drm_intel_bo_wait_rendering(f->bo); + drm_intel_bo_unreference(f->bo); + f->bo = NULL; + + return 0; +} + +void +intel_drm_winsys_init_fence_functions(struct intel_drm_winsys *idws) +{ + idws->base.fence_reference = intel_drm_fence_reference; + idws->base.fence_signalled = intel_drm_fence_signalled; + idws->base.fence_finish = intel_drm_fence_finish; +} diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_winsys.h b/src/gallium/winsys/drm/intel/gem/intel_drm_winsys.h new file mode 100644 index 0000000000..415c45feea --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_winsys.h @@ -0,0 +1,78 @@ + +#ifndef INTEL_DRM_WINSYS_H +#define INTEL_DRM_WINSYS_H + +#include "i915simple/intel_batchbuffer.h" + +#include "drm.h" +#include "intel_bufmgr.h" + + +/* + * Winsys + */ + + +struct intel_drm_winsys +{ + struct intel_winsys base; + + boolean softpipe; + boolean dump_cmd; + + int fd; /**< Drm file discriptor */ + + unsigned id; + + size_t max_batch_size; + + struct { + drm_intel_bufmgr *gem; + } pools; +}; + +static INLINE struct intel_drm_winsys * +intel_drm_winsys(struct intel_winsys *iws) +{ + return (struct intel_drm_winsys *)iws; +} + +struct intel_drm_winsys * intel_drm_winsys_create(int fd, unsigned pci_id); +struct pipe_fence_handle * intel_drm_fence_create(drm_intel_bo *bo); + +void intel_drm_winsys_init_batchbuffer_functions(struct intel_drm_winsys *idws); +void intel_drm_winsys_init_buffer_functions(struct intel_drm_winsys *idws); +void intel_drm_winsys_init_fence_functions(struct intel_drm_winsys *idws); + + +/* + * Buffer + */ + + +struct intel_drm_buffer { + unsigned magic; + + drm_intel_bo *bo; + + void *ptr; + unsigned map_count; + boolean map_gtt; + + boolean flinked; + unsigned flink; +}; + +static INLINE struct intel_drm_buffer * +intel_drm_buffer(struct intel_buffer *buffer) +{ + return (struct intel_drm_buffer *)buffer; +} + +static INLINE drm_intel_bo * +intel_bo(struct intel_buffer *buffer) +{ + return intel_drm_buffer(buffer)->bo; +} + +#endif diff --git a/src/gallium/winsys/drm/intel/xorg/Makefile b/src/gallium/winsys/drm/intel/xorg/Makefile index d51cca8d21..9e56853b02 100644 --- a/src/gallium/winsys/drm/intel/xorg/Makefile +++ b/src/gallium/winsys/drm/intel/xorg/Makefile @@ -19,6 +19,7 @@ LIBS = \ $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \ $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \ $(TOP)/src/gallium/drivers/i915simple/libi915simple.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(GALLIUM_AUXILIARIES) diff --git a/src/gallium/winsys/drm/intel/xorg/intel_xorg.c b/src/gallium/winsys/drm/intel/xorg/intel_xorg.c index 46a7971f60..369dc356cf 100644 --- a/src/gallium/winsys/drm/intel/xorg/intel_xorg.c +++ b/src/gallium/winsys/drm/intel/xorg/intel_xorg.c @@ -47,8 +47,8 @@ static SymTabRec intel_xorg_chipsets[] = { }; static PciChipsets intel_xorg_pci_devices[] = { - {PCI_MATCH_ANY, PCI_MATCH_ANY, RES_SHARED_VGA}, - {-1, -1, RES_UNDEFINED} + {PCI_MATCH_ANY, PCI_MATCH_ANY, NULL}, + {-1, -1, NULL} }; static XF86ModuleVersionInfo intel_xorg_version = { @@ -105,12 +105,6 @@ intel_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin) xf86AddDriver(&modesetting, module, HaveDriverFuncs); /* - * Tell the loader about symbols from other modules that this module - * might refer to. - */ - xorg_tracker_loader_ref_sym_lists(); - - /* * The return value must be non-NULL on success even though there * is no TearDownProc. */ @@ -140,7 +134,7 @@ intel_xorg_pci_probe(DriverPtr driver, NULL, NULL, NULL, NULL, NULL); if (scrn != NULL) { scrn->driverVersion = 1; - scrn->driverName = "modesetting"; + scrn->driverName = "i915"; scrn->name = "modesetting"; scrn->Probe = NULL; 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 3167ccfdc1..117ca6059b 100644 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c @@ -12,51 +12,37 @@ #include "nouveau/nouveau_screen.h" static struct pipe_surface * -dri_surface_from_handle(struct drm_api *api, struct pipe_screen *screen, - unsigned handle, - enum pipe_format format, - unsigned width, - unsigned height, - unsigned pitch) +dri_surface_from_handle(struct drm_api *api, struct pipe_screen *pscreen, + unsigned handle, enum pipe_format format, + unsigned width, unsigned height, unsigned pitch) { - struct pipe_surface *surface = NULL; - struct pipe_texture *texture = NULL; - struct pipe_texture templat; - struct pipe_buffer *buf = NULL; - - buf = api->buffer_from_handle(api, screen, "front buffer", handle); - if (!buf) - return NULL; - - memset(&templat, 0, sizeof(templat)); - templat.tex_usage = PIPE_TEXTURE_USAGE_PRIMARY | - NOUVEAU_TEXTURE_USAGE_LINEAR; - templat.target = PIPE_TEXTURE_2D; - templat.last_level = 0; - templat.depth[0] = 1; - templat.format = format; - templat.width[0] = width; - templat.height[0] = height; - pf_get_block(templat.format, &templat.block); - - texture = screen->texture_blanket(screen, - &templat, - &pitch, - buf); - - /* we don't need the buffer from this point on */ - pipe_buffer_reference(&buf, NULL); - - if (!texture) - return NULL; - - surface = screen->get_tex_surface(screen, texture, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - - /* we don't need the texture from this point on */ - pipe_texture_reference(&texture, NULL); - return surface; + struct pipe_surface *ps = NULL; + struct pipe_texture *pt = NULL; + struct pipe_texture tmpl; + + memset(&tmpl, 0, sizeof(tmpl)); + tmpl.tex_usage = PIPE_TEXTURE_USAGE_PRIMARY | + NOUVEAU_TEXTURE_USAGE_LINEAR; + tmpl.target = PIPE_TEXTURE_2D; + tmpl.last_level = 0; + tmpl.depth[0] = 1; + tmpl.format = format; + tmpl.width[0] = width; + tmpl.height[0] = height; + pf_get_block(tmpl.format, &tmpl.block); + + pt = api->texture_from_shared_handle(api, pscreen, &tmpl, + "front buffer", pitch, handle); + if (!pt) + return NULL; + + ps = pscreen->get_tex_surface(pscreen, pt, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* we don't need the texture from this point on */ + pipe_texture_reference(&pt, NULL); + return ps; } static struct pipe_surface * @@ -126,7 +112,7 @@ nouveau_drm_create_screen(struct drm_api *api, int fd, return NULL; } - if (arg->mode == DRM_CREATE_DRI1) { + if (arg && arg->mode == DRM_CREATE_DRI1) { struct nouveau_dri *nvdri = dri1->ddx_info; enum pipe_format format; @@ -205,16 +191,10 @@ nouveau_drm_create_context(struct drm_api *api, struct pipe_screen *pscreen) return nvws->pctx[i]; } -static boolean -nouveau_drm_pb_from_pt(struct drm_api *api, struct pipe_texture *pt, - struct pipe_buffer **ppb, unsigned *stride) -{ - return false; -} - -static struct pipe_buffer * -nouveau_drm_pb_from_handle(struct drm_api *api, struct pipe_screen *pscreen, - const char *name, unsigned handle) +static struct pipe_texture * +nouveau_drm_pt_from_name(struct drm_api *api, struct pipe_screen *pscreen, + struct pipe_texture *templ, const char *name, + unsigned stride, unsigned handle) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct pipe_buffer *pb; @@ -238,41 +218,42 @@ nouveau_drm_pb_from_handle(struct drm_api *api, struct pipe_screen *pscreen, pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE | PIPE_BUFFER_USAGE_CPU_READ_WRITE; pb->size = nouveau_bo(pb)->size; - return pb; + return pscreen->texture_blanket(pscreen, templ, &stride, pb); } static boolean -nouveau_drm_handle_from_pb(struct drm_api *api, struct pipe_screen *pscreen, - struct pipe_buffer *pb, unsigned *handle) +nouveau_drm_name_from_pt(struct drm_api *api, struct pipe_screen *pscreen, + struct pipe_texture *pt, unsigned *stride, + unsigned *handle) { - struct nouveau_bo *bo = nouveau_bo(pb); + struct nouveau_miptree *mt = nouveau_miptree(pt); - if (!bo) - return FALSE; + if (!mt || !mt->bo) + return false; - *handle = bo->handle; - return TRUE; + return nouveau_bo_handle_get(mt->bo, handle) == 0; } static boolean -nouveau_drm_name_from_pb(struct drm_api *api, struct pipe_screen *pscreen, - struct pipe_buffer *pb, unsigned *handle) +nouveau_drm_handle_from_pt(struct drm_api *api, struct pipe_screen *pscreen, + struct pipe_texture *pt, unsigned *stride, + unsigned *handle) { - struct nouveau_bo *bo = nouveau_bo(pb); + struct nouveau_miptree *mt = nouveau_miptree(pt); - if (!bo) - return FALSE; + if (!mt || !mt->bo) + return false; - return nouveau_bo_handle_get(bo, handle) == 0; + *handle = mt->bo->handle; + return true; } struct drm_api drm_api_hooks = { .create_screen = nouveau_drm_create_screen, .create_context = nouveau_drm_create_context, - .buffer_from_texture = nouveau_drm_pb_from_pt, - .buffer_from_handle = nouveau_drm_pb_from_handle, - .handle_from_buffer = nouveau_drm_handle_from_pb, - .global_handle_from_buffer = nouveau_drm_name_from_pb, + .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, }; struct drm_api * diff --git a/src/gallium/winsys/drm/nouveau/xorg/Makefile b/src/gallium/winsys/drm/nouveau/xorg/Makefile new file mode 100644 index 0000000000..f0d3b337e8 --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/xorg/Makefile @@ -0,0 +1,61 @@ +TARGET = modesetting_drv.so +CFILES = $(wildcard ./*.c) +OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES)) +TOP = ../../../../../.. + +include $(TOP)/configs/current + +INCLUDES = \ + $(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \ + -I../gem \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/mesa \ + -I$(TOP)/include \ + -I$(TOP)/src/egl/main + +LIBS = \ + $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \ + $(TOP)/src/gallium/winsys/drm/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 \ + $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \ + $(GALLIUM_AUXILIARIES) + +DRIVER_DEFINES = \ + -DHAVE_CONFIG_H + + +############################################# + + + +all default: $(TARGET) + +$(TARGET): $(OBJECTS) Makefile $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a $(LIBS) + $(TOP)/bin/mklib -noprefix -o $@ \ + $(OBJECTS) $(LIBS) $(shell pkg-config --libs libdrm) -ldrm_nouveau + +clean: + rm -rf $(OBJECTS) $(TARGET) + +install: + $(INSTALL) -d $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) + $(MINSTALL) -m 755 $(TARGET) $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) + + +############################################## + + +.c.o: + $(CC) -c $(CFLAGS) $(INCLUDES) $(DRIVER_DEFINES) $< -o $@ + + +############################################## + +.PHONY = all clean install diff --git a/src/gallium/winsys/drm/nouveau/xorg/nouveau_xorg.c b/src/gallium/winsys/drm/nouveau/xorg/nouveau_xorg.c new file mode 100644 index 0000000000..a669b3080a --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/xorg/nouveau_xorg.c @@ -0,0 +1,149 @@ +/* + * 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 <alanh@tungstengraphics.com> + * Author: Jakob Bornecrantz <wallbraker@gmail.com> + * + */ + +#include "../../../../state_trackers/xorg/xorg_winsys.h" + +static void nouveau_xorg_identify(int flags); +static Bool nouveau_xorg_pci_probe(DriverPtr driver, int entity_num, + struct pci_device *device, + intptr_t match_data); + +static const struct pci_id_match nouveau_xorg_device_match[] = { + { 0x10de, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, + 0x00030000, 0x00ffffff, 0 }, + { 0x12d2, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, + 0x00030000, 0x00ffffff, 0 }, + {0, 0, 0}, +}; + +static SymTabRec nouveau_xorg_chipsets[] = { + {PCI_MATCH_ANY, "NVIDIA Graphics Device"}, + {-1, NULL} +}; + +static PciChipsets nouveau_xorg_pci_devices[] = { + {PCI_MATCH_ANY, PCI_MATCH_ANY, NULL}, + {-1, -1, NULL} +}; + +static XF86ModuleVersionInfo nouveau_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", + nouveau_xorg_identify, + NULL, + xorg_tracker_available_options, + NULL, + 0, + NULL, + nouveau_xorg_device_match, + nouveau_xorg_pci_probe +}; + +static MODULESETUPPROTO(nouveau_xorg_setup); + +_X_EXPORT XF86ModuleData modesettingModuleData = { + &nouveau_xorg_version, + nouveau_xorg_setup, + NULL +}; + +/* + * Xorg driver functions + */ + +static pointer +nouveau_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 +nouveau_xorg_identify(int flags) +{ + xf86PrintChipsets("modesetting", "Driver for Modesetting Kernel Drivers", + nouveau_xorg_chipsets); +} + +static Bool +nouveau_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, nouveau_xorg_pci_devices, + NULL, NULL, NULL, NULL, NULL); + if (scrn != NULL) { + scrn->driverVersion = 1; + scrn->driverName = "i915"; + 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/radeon/core/radeon_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c index 684a487f24..7bf23cba23 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c @@ -32,6 +32,8 @@ #include "radeon_buffer.h" +#include "radeon_bo_gem.h" + static const char *radeon_get_name(struct pipe_winsys *ws) { return "Radeon/GEM+KMS"; @@ -72,6 +74,7 @@ static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws, alignment, domain, 0); if (radeon_buffer->bo == NULL) { FREE(radeon_buffer); + return NULL; } return &radeon_buffer->base; } @@ -98,6 +101,7 @@ static struct pipe_buffer *radeon_surface_buffer_create(struct pipe_winsys *ws, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { struct pipe_format_block block; @@ -134,17 +138,19 @@ static void *radeon_buffer_map(struct pipe_winsys *ws, int write = 0; if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { - /* XXX Remove this when radeon_bo_map supports DONTBLOCK */ - return NULL; + uint32_t domain; + + if (radeon_bo_is_busy(radeon_buffer->bo, &domain)) + return NULL; } if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) { write = 1; } - radeon_bo_wait(radeon_buffer->bo); - - if (radeon_bo_map(radeon_buffer->bo, write)) + if (radeon_bo_map(radeon_buffer->bo, write)) { return NULL; + } + return radeon_buffer->bo->ptr; } @@ -187,7 +193,6 @@ static void radeon_flush_frontbuffer(struct pipe_winsys *pipe_winsys, struct radeon_winsys* radeon_pipe_winsys(int fd) { struct radeon_winsys* radeon_ws; - struct radeon_bo_manager* bom; radeon_ws = CALLOC_STRUCT(radeon_winsys); if (radeon_ws == NULL) { diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h index 8c8b61fa10..f5153b06af 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h @@ -61,11 +61,6 @@ struct radeon_winsys_priv { /* Radeon BO manager. */ struct radeon_bo_manager* bom; - /* Radeon BO space checker. */ - struct radeon_cs_space_check sc[RADEON_MAX_BOS]; - /* Current BO count. */ - unsigned bo_count; - /* Radeon CS manager. */ struct radeon_cs_manager* csm; diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.c b/src/gallium/winsys/drm/radeon/core/radeon_drm.c index da2010184a..a4011db0b8 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.c @@ -26,15 +26,15 @@ /* * Authors: * Corbin Simpson <MostAwesomeDude@gmail.com> + * Joakim Sindholt <opensource@zhasha.com> */ #include "radeon_drm.h" -#include "trace/tr_drm.h" /* Create a pipe_screen. */ struct pipe_screen* radeon_create_screen(struct drm_api* api, int drmFB, - struct drm_create_screen_arg *arg) + struct drm_create_screen_arg *arg) { struct radeon_winsys* winsys = radeon_pipe_winsys(drmFB); @@ -54,7 +54,8 @@ struct pipe_context* radeon_create_context(struct drm_api* api, if (getenv("RADEON_SOFTPIPE")) { return radeon_create_softpipe(screen->winsys); } else { - return r300_create_context(screen, screen->winsys); + return r300_create_context(screen, + (struct r300_winsys*)screen->winsys); } } @@ -97,27 +98,40 @@ struct pipe_buffer* radeon_buffer_from_handle(struct drm_api* api, return &radeon_buffer->base; } -boolean radeon_handle_from_buffer(struct drm_api* api, - struct pipe_screen* screen, - struct pipe_buffer* buffer, - unsigned* handle) +static struct pipe_texture* +radeon_texture_from_shared_handle(struct drm_api *api, + struct pipe_screen *screen, + struct pipe_texture *templ, + const char *name, + unsigned stride, + unsigned handle) { - struct radeon_pipe_buffer* radeon_buffer = - (struct radeon_pipe_buffer*)buffer; - *handle = radeon_buffer->bo->handle; - return TRUE; + struct pipe_buffer *buffer; + + buffer = radeon_buffer_from_handle(api, screen, name, handle); + if (!buffer) { + return NULL; + } + + return screen->texture_blanket(screen, templ, &stride, buffer); } -boolean radeon_global_handle_from_buffer(struct drm_api* api, - struct pipe_screen* screen, - struct pipe_buffer* buffer, - unsigned* handle) +static boolean radeon_shared_handle_from_texture(struct drm_api *api, + struct pipe_screen *screen, + struct pipe_texture *texture, + unsigned *stride, + unsigned *handle) { int retval, fd; struct drm_gem_flink flink; - struct radeon_pipe_buffer* radeon_buffer = - (struct radeon_pipe_buffer*)buffer; + struct radeon_pipe_buffer* radeon_buffer; + struct pipe_buffer *buffer; + + if (!radeon_buffer_from_texture(api, texture, &buffer, stride)) { + return FALSE; + } + radeon_buffer = (struct radeon_pipe_buffer*)buffer; if (!radeon_buffer->flinked) { fd = ((struct radeon_winsys*)screen->winsys)->priv->fd; @@ -138,13 +152,30 @@ boolean radeon_global_handle_from_buffer(struct drm_api* api, return TRUE; } +static boolean radeon_local_handle_from_texture(struct drm_api *api, + struct pipe_screen *screen, + struct pipe_texture *texture, + unsigned *stride, + unsigned *handle) +{ + struct pipe_buffer *buffer; + if (!radeon_buffer_from_texture(api, texture, &buffer, stride)) { + return FALSE; + } + + *handle = ((struct radeon_pipe_buffer*)buffer)->bo->handle; + + pipe_buffer_reference(&buffer, NULL); + + return TRUE; +} + struct drm_api drm_api_hooks = { .create_screen = radeon_create_screen, .create_context = radeon_create_context, - .buffer_from_texture = radeon_buffer_from_texture, - .buffer_from_handle = radeon_buffer_from_handle, - .handle_from_buffer = radeon_handle_from_buffer, - .global_handle_from_buffer = radeon_global_handle_from_buffer, + .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, }; 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 8560f71db6..88a5c82b28 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.h @@ -30,8 +30,13 @@ #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_memory.h" #include "state_tracker/drm_api.h" @@ -40,6 +45,9 @@ #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); diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.c b/src/gallium/winsys/drm/radeon/core/radeon_r300.c index 8c5f756ddf..d2d84f1a8f 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.c @@ -27,66 +27,25 @@ static boolean radeon_r300_add_buffer(struct r300_winsys* winsys, uint32_t rd, uint32_t wd) { - int i; struct radeon_winsys_priv* priv = (struct radeon_winsys_priv*)winsys->radeon_winsys; - struct radeon_cs_space_check* sc = priv->sc; struct radeon_bo* bo = ((struct radeon_pipe_buffer*)pbuffer)->bo; - /* Check to see if this BO is already in line for validation; - * find a slot for it otherwise. */ - for (i = 0; i < priv->bo_count; i++) { - if (sc[i].bo == bo) { - sc[i].read_domains |= rd; - sc[i].write_domain |= wd; - return TRUE; - } - } - - if (priv->bo_count >= RADEON_MAX_BOS) { - /* Dohoho. Not falling for that one again. Request a flush. */ - return FALSE; - } - - sc[priv->bo_count].bo = bo; - sc[priv->bo_count].read_domains = rd; - sc[priv->bo_count].write_domain = wd; - priv->bo_count++; - + radeon_cs_space_add_persistent_bo(priv->cs, bo, rd, wd); return TRUE; } static boolean radeon_r300_validate(struct r300_winsys* winsys) { - int retval, i; struct radeon_winsys_priv* priv = (struct radeon_winsys_priv*)winsys->radeon_winsys; - struct radeon_cs_space_check* sc = priv->sc; - - retval = radeon_cs_space_check(priv->cs, sc, priv->bo_count); - - if (retval == RADEON_CS_SPACE_OP_TO_BIG) { - /* We might as well HCF, since this is not going to fit in the card, - * period. */ - /* XXX just drop it on the floor instead */ - exit(1); - } else if (retval == RADEON_CS_SPACE_FLUSH) { - /* We must flush before more rendering can commence. */ - return TRUE; - } - /* XXX should probably be its own function */ - for (i = 0; i < priv->bo_count; i++) { - if (sc[i].read_domains && sc[i].write_domain) { - /* Cute, cute. We need to flush first. */ - debug_printf("radeon: BO %p can't be read and written; " - "requesting flush.\n", sc[i].bo); - return TRUE; - } + if (radeon_cs_space_check(priv->cs) < 0) { + return FALSE; } /* Things are fine, we can proceed as normal. */ - return FALSE; + return TRUE; } static boolean radeon_r300_check_cs(struct r300_winsys* winsys, int size) @@ -151,8 +110,7 @@ static void radeon_r300_flush_cs(struct r300_winsys* winsys) { struct radeon_winsys_priv* priv = (struct radeon_winsys_priv*)winsys->radeon_winsys; - struct radeon_cs_space_check* sc = priv->sc; - int retval = 1; + int retval; /* Emit the CS. */ retval = radeon_cs_emit(priv->cs); @@ -160,44 +118,48 @@ static void radeon_r300_flush_cs(struct r300_winsys* winsys) debug_printf("radeon: Bad CS, dumping...\n"); radeon_cs_print(priv->cs, stderr); } - radeon_cs_erase(priv->cs); /* Clean out BOs. */ - memset(sc, 0, sizeof(struct radeon_cs_space_check) * RADEON_MAX_BOS); - priv->bo_count = 0; + radeon_cs_space_reset_bos(priv->cs); + + /* Reset CS. + * Someday, when we care about performance, we should really find a way + * to rotate between two or three CS objects so that the GPU can be + * spinning through one CS while another one is being filled. */ + radeon_cs_erase(priv->cs); } /* Helper function to do the ioctls needed for setup and init. */ static void do_ioctls(struct r300_winsys* winsys, int fd) { struct drm_radeon_gem_info gem_info = {0}; - drm_radeon_getparam_t gp = {0}; struct drm_radeon_info info = {0}; int target = 0; int retval; - info.value = ⌖ - gp.value = ⌖ + info.value = (unsigned long)⌖ + + /* First, get the number of pixel pipes */ + info.request = RADEON_INFO_NUM_GB_PIPES; + retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); + if (retval) { + fprintf(stderr, "%s: Failed to get GB pipe count, " + "error number %d\n", __FUNCTION__, retval); + exit(1); + } + winsys->gb_pipes = target; - /* First, get PCI ID */ + /* Then, get PCI ID */ info.request = RADEON_INFO_DEVICE_ID; retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); if (retval) { - fprintf(stderr, "%s: New ioctl for PCI ID failed " - "(error number %d), trying classic ioctl...\n", - __FUNCTION__, retval); - gp.param = RADEON_PARAM_DEVICE_ID; - retval = drmCommandWriteRead(fd, DRM_RADEON_GETPARAM, &gp, - sizeof(gp)); - if (retval) { - fprintf(stderr, "%s: Failed to get PCI ID, " - "error number %d\n", __FUNCTION__, retval); - exit(1); - } + fprintf(stderr, "%s: Failed to get PCI ID, " + "error number %d\n", __FUNCTION__, retval); + exit(1); } winsys->pci_id = target; - /* Then, retrieve MM info */ + /* Finally, retrieve MM info */ retval = drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO, &gem_info, sizeof(gem_info)); 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 a2e0e58248..775d7937fd 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.h @@ -20,29 +20,23 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#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.h" +#include "radeon_cs_gem.h" #include "r300_winsys.h" #include "radeon_buffer.h" -/* protect us from bonghits */ -#ifndef RADEON_INFO_DEVICE_ID -#define RADEON_INFO_DEVICE_ID 0 -#endif -#ifndef DRM_RADEON_INFO -#define DRM_RADEON_INFO 0x1 -struct drm_radeon_info { - uint32_t request; - uint32_t pad; - uint64_t value; -}; -#endif +struct radeon_winsys; struct r300_winsys* radeon_create_r300_winsys(int fd, struct radeon_winsys* old_winsys); + +#endif /* RADEON_R300_H */ diff --git a/src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c b/src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c index 36824251f0..837f2aa8fe 100644 --- a/src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c +++ b/src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c @@ -48,8 +48,8 @@ static SymTabRec radeon_xorg_chipsets[] = { }; static PciChipsets radeon_xorg_pci_devices[] = { - {PCI_MATCH_ANY, PCI_MATCH_ANY, RES_SHARED_VGA}, - {-1, -1, RES_UNDEFINED} + {PCI_MATCH_ANY, PCI_MATCH_ANY, NULL}, + {-1, -1, NULL} }; static XF86ModuleVersionInfo radeon_xorg_version = { @@ -106,12 +106,6 @@ radeon_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin) xf86AddDriver(&modesetting, module, HaveDriverFuncs); /* - * Tell the loader about symbols from other modules that this module - * might refer to. - */ - xorg_tracker_loader_ref_sym_lists(); - - /* * The return value must be non-NULL on success even though there * is no TearDownProc. */ @@ -141,7 +135,7 @@ radeon_xorg_pci_probe(DriverPtr driver, NULL, NULL, NULL, NULL, NULL); if (scrn != NULL) { scrn->driverVersion = 1; - scrn->driverName = "modesetting"; + scrn->driverName = "radeon"; scrn->name = "modesetting"; scrn->Probe = NULL; diff --git a/src/gallium/winsys/egl_xlib/Makefile b/src/gallium/winsys/egl_xlib/Makefile index a33a50ec22..3efb7ed4af 100644 --- a/src/gallium/winsys/egl_xlib/Makefile +++ b/src/gallium/winsys/egl_xlib/Makefile @@ -37,7 +37,7 @@ UNUSED_LIBS = \ $(TOP)/src/mesa/libmesagallium.a \ -LOCAL_CFLAGS = -D_EGL_PLATFORM_X=1 +LOCAL_CFLAGS = .c.o: diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c index e1ddcae97b..d02f825047 100644 --- a/src/gallium/winsys/egl_xlib/egl_xlib.c +++ b/src/gallium/winsys/egl_xlib/egl_xlib.c @@ -33,6 +33,7 @@ #include <dlfcn.h> +#include <X11/Xlib.h> #include <X11/Xutil.h> #include "pipe/p_compiler.h" @@ -61,6 +62,14 @@ struct xlib_egl_driver { _EGLDriver Base; /**< base class */ + EGLint apis; +}; + + +/** driver data of _EGLDisplay */ +struct xlib_egl_display +{ + Display *Dpy; struct pipe_winsys *winsys; struct pipe_screen *screen; @@ -82,6 +91,7 @@ struct xlib_egl_surface { _EGLSurface Base; /**< base class */ + /* These are set for window surface */ Display *Dpy; /**< The X Display of the window */ Window Win; /**< The user-created window ID */ GC Gc; @@ -93,6 +103,12 @@ struct xlib_egl_surface }; +static void +flush_frontbuffer(struct pipe_winsys *pws, + struct pipe_surface *psurf, + void *context_private); + + /** cast wrapper */ static INLINE struct xlib_egl_driver * xlib_egl_driver(_EGLDriver *drv) @@ -101,19 +117,24 @@ xlib_egl_driver(_EGLDriver *drv) } -static struct xlib_egl_surface * -lookup_surface(EGLSurface surf) +static INLINE struct xlib_egl_display * +xlib_egl_display(_EGLDisplay *dpy) { - _EGLSurface *surface = _eglLookupSurface(surf); - return (struct xlib_egl_surface *) surface; + return (struct xlib_egl_display *) dpy->DriverData; } -static struct xlib_egl_context * -lookup_context(EGLContext surf) +static INLINE struct xlib_egl_surface * +lookup_surface(_EGLSurface *surf) { - _EGLContext *context = _eglLookupContext(surf); - return (struct xlib_egl_context *) context; + return (struct xlib_egl_surface *) surf; +} + + +static INLINE struct xlib_egl_context * +lookup_context(_EGLContext *ctx) +{ + return (struct xlib_egl_context *) ctx; } @@ -132,19 +153,18 @@ bitcount(unsigned int n) * Create the EGLConfigs. (one per X visual) */ static void -create_configs(_EGLDriver *drv, EGLDisplay dpy) +create_configs(struct xlib_egl_display *xdpy, _EGLDisplay *disp) { static const EGLint all_apis = (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENVG_BIT | EGL_OPENGL_BIT); - _EGLDisplay *disp = _eglLookupDisplay(dpy); XVisualInfo *visInfo, visTemplate; int num_visuals, i; /* get list of all X visuals, create an EGL config for each */ - visTemplate.screen = DefaultScreen(disp->Xdpy); - visInfo = XGetVisualInfo(disp->Xdpy, VisualScreenMask, + visTemplate.screen = DefaultScreen(xdpy->Dpy); + visInfo = XGetVisualInfo(xdpy->Dpy, VisualScreenMask, &visTemplate, &num_visuals); if (!visInfo) { printf("egl_xlib.c: couldn't get any X visuals\n"); @@ -180,10 +200,14 @@ create_configs(_EGLDriver *drv, EGLDisplay dpy) SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_FALSE); SET_CONFIG_ATTRIB(config, EGL_CONFORMANT, all_apis); SET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE, all_apis); - SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); + SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT); + SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); + SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); _eglAddConfig(disp, config); } + + XFree(visInfo); } @@ -191,16 +215,47 @@ create_configs(_EGLDriver *drv, EGLDisplay dpy) * Called via eglInitialize(), drv->API.Initialize(). */ static EGLBoolean -xlib_eglInitialize(_EGLDriver *drv, EGLDisplay dpy, - EGLint *minor, EGLint *major) +xlib_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, + EGLint *major, EGLint *minor) { - create_configs(drv, dpy); + struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); + struct xlib_egl_display *xdpy; + + xdpy = CALLOC_STRUCT(xlib_egl_display); + if (!xdpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + xdpy->Dpy = (Display *) dpy->NativeDisplay; + if (!xdpy->Dpy) { + xdpy->Dpy = XOpenDisplay(NULL); + if (!xdpy->Dpy) { + free(xdpy); + return EGL_FALSE; + } + } - drv->Initialized = EGL_TRUE; + /* create winsys and pipe screen */ + xdpy->winsys = create_sw_winsys(); + if (!xdpy->winsys) { + free(xdpy); + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + } + xdpy->winsys->flush_frontbuffer = flush_frontbuffer; + xdpy->screen = softpipe_create_screen(xdpy->winsys); + if (!xdpy->screen) { + free(xdpy->winsys); + free(xdpy); + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + } + + dpy->DriverData = (void *) xdpy; + dpy->ClientAPIsMask = xdrv->apis; + + create_configs(xdpy, dpy); /* we're supporting EGL 1.4 */ - *minor = 1; - *major = 4; + *major = 1; + *minor = 4; return EGL_TRUE; } @@ -210,8 +265,20 @@ xlib_eglInitialize(_EGLDriver *drv, EGLDisplay dpy, * Called via eglTerminate(), drv->API.Terminate(). */ static EGLBoolean -xlib_eglTerminate(_EGLDriver *drv, EGLDisplay dpy) +xlib_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy) { + struct xlib_egl_display *xdpy = xlib_egl_display(dpy); + + _eglReleaseDisplayResources(drv, dpy); + _eglCleanupDisplay(dpy); + + xdpy->screen->destroy(xdpy->screen); + free(xdpy->winsys); + + if (!dpy->NativeDisplay) + XCloseDisplay(xdpy->Dpy); + free(xdpy); + return EGL_TRUE; } @@ -264,7 +331,13 @@ static void check_and_update_buffer_size(struct xlib_egl_surface *surface) { uint width, height; - get_drawable_size(surface->Dpy, surface->Win, &width, &height); + if (surface->Base.Type == EGL_PBUFFER_BIT) { + width = surface->Base.Width; + height = surface->Base.Height; + } + else { + get_drawable_size(surface->Dpy, surface->Win, &width, &height); + } st_resize_framebuffer(surface->Framebuffer, width, height); surface->Base.Width = width; surface->Base.Height = height; @@ -281,6 +354,9 @@ display_surface(struct pipe_winsys *pws, XImage *ximage; void *data; + if (xsurf->Base.Type == EGL_PBUFFER_BIT) + return; + ximage = XCreateImage(xsurf->Dpy, xsurf->VisInfo.visual, xsurf->VisInfo.depth, @@ -330,24 +406,23 @@ flush_frontbuffer(struct pipe_winsys *pws, /** * Called via eglCreateContext(), drv->API.CreateContext(). */ -static EGLContext -xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, - EGLContext share_list, const EGLint *attrib_list) +static _EGLContext * +xlib_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + _EGLContext *share_list, const EGLint *attrib_list) { - struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); - _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); + struct xlib_egl_display *xdpy = xlib_egl_display(dpy); struct xlib_egl_context *ctx; struct st_context *share_ctx = NULL; /* XXX fix */ __GLcontextModes visual; ctx = CALLOC_STRUCT(xlib_egl_context); if (!ctx) - return EGL_NO_CONTEXT; + return NULL; /* let EGL lib init the common stuff */ if (!_eglInitContext(drv, &ctx->Base, conf, attrib_list)) { free(ctx); - return EGL_NO_CONTEXT; + return NULL; } /* API-dependent context creation */ @@ -359,7 +434,7 @@ xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, /* fall-through */ case EGL_OPENGL_API: /* create a softpipe context */ - ctx->pipe = softpipe_create(xdrv->screen); + ctx->pipe = softpipe_create(xdpy->screen); /* Now do xlib / state tracker inits here */ _eglConfigToContextModesRec(conf, &visual); ctx->Context = st_create_context(ctx->pipe, &visual, share_ctx); @@ -367,41 +442,33 @@ xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, default: _eglError(EGL_BAD_MATCH, "eglCreateContext(unsupported API)"); free(ctx); - return EGL_NO_CONTEXT; + return NULL; } - _eglLinkContext(&ctx->Base, _eglLookupDisplay(dpy)); - - return _eglGetContextHandle(&ctx->Base); + return &ctx->Base; } static EGLBoolean -xlib_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) +xlib_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) { struct xlib_egl_context *context = lookup_context(ctx); - if (context) { - _eglUnlinkContext(&context->Base); - if (!context->Base.IsBound) { - /* API-dependent clean-up */ - switch (context->Base.ClientAPI) { - case EGL_OPENGL_ES_API: - case EGL_OPENVG_API: - /* fall-through */ - case EGL_OPENGL_API: - st_destroy_context(context->Context); - break; - default: - assert(0); - } - free(context); + + if (!_eglIsContextBound(&context->Base)) { + /* API-dependent clean-up */ + switch (context->Base.ClientAPI) { + case EGL_OPENGL_ES_API: + case EGL_OPENVG_API: + /* fall-through */ + case EGL_OPENGL_API: + st_destroy_context(context->Context); + break; + default: + assert(0); } - return EGL_TRUE; - } - else { - _eglError(EGL_BAD_CONTEXT, "eglDestroyContext"); - return EGL_TRUE; + free(context); } + return EGL_TRUE; } @@ -409,16 +476,25 @@ xlib_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) * Called via eglMakeCurrent(), drv->API.MakeCurrent(). */ static EGLBoolean -xlib_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, - EGLSurface draw, EGLSurface read, EGLContext ctx) +xlib_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) { struct xlib_egl_context *context = lookup_context(ctx); struct xlib_egl_surface *draw_surf = lookup_surface(draw); struct xlib_egl_surface *read_surf = lookup_surface(read); + struct st_context *oldcontext = NULL; + _EGLContext *oldctx; + + oldctx = _eglGetCurrentContext(); + if (oldctx && _eglIsContextLinked(oldctx)) + oldcontext = st_get_current(); - if (!_eglMakeCurrent(drv, dpy, draw, read, context)) + if (!_eglMakeCurrent(drv, dpy, draw, read, ctx)) return EGL_FALSE; + /* Flush before switching context. Check client API? */ + if (oldcontext) + st_flush(oldcontext, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); st_make_current((context ? context->Context : NULL), (draw_surf ? draw_surf->Framebuffer : NULL), (read_surf ? read_surf->Framebuffer : NULL)); @@ -472,39 +548,34 @@ choose_stencil_format(const __GLcontextModes *visual) /** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ -static EGLSurface -xlib_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +static _EGLSurface * +xlib_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list) { - struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); - _EGLDisplay *disp = _eglLookupDisplay(dpy); - _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); - + struct xlib_egl_display *xdpy = xlib_egl_display(disp); struct xlib_egl_surface *surf; __GLcontextModes visual; uint width, height; surf = CALLOC_STRUCT(xlib_egl_surface); if (!surf) - return EGL_NO_SURFACE; + return NULL; /* Let EGL lib init the common stuff */ if (!_eglInitSurface(drv, &surf->Base, EGL_WINDOW_BIT, conf, attrib_list)) { free(surf); - return EGL_NO_SURFACE; + return NULL; } - _eglLinkSurface(&surf->Base, disp); - /* * Now init the Xlib and gallium stuff */ surf->Win = (Window) window; /* The X window ID */ - surf->Dpy = disp->Xdpy; /* The X display */ + surf->Dpy = xdpy->Dpy; /* The X display */ surf->Gc = XCreateGC(surf->Dpy, surf->Win, 0, NULL); - surf->winsys = xdrv->winsys; + surf->winsys = xdpy->winsys; _eglConfigToContextModesRec(conf, &visual); get_drawable_size(surf->Dpy, surf->Win, &width, &height); @@ -523,32 +594,172 @@ xlib_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, st_resize_framebuffer(surf->Framebuffer, width, height); - return _eglGetSurfaceHandle(&surf->Base); + return &surf->Base; +} + + +static _EGLSurface * +xlib_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, + const EGLint *attrib_list) +{ + struct xlib_egl_display *xdpy = xlib_egl_display(disp); + struct xlib_egl_surface *surf; + __GLcontextModes visual; + uint width, height; + EGLBoolean bind_texture; + + surf = CALLOC_STRUCT(xlib_egl_surface); + if (!surf) { + _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); + return NULL; + } + + if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT, + conf, attrib_list)) { + free(surf); + return NULL; + } + if (surf->Base.Width < 0 || surf->Base.Height < 0) { + _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferSurface"); + free(surf); + return NULL; + } + + bind_texture = (surf->Base.TextureFormat != EGL_NO_TEXTURE); + width = (uint) surf->Base.Width; + height = (uint) surf->Base.Height; + if ((surf->Base.TextureTarget == EGL_NO_TEXTURE && bind_texture) || + (surf->Base.TextureTarget != EGL_NO_TEXTURE && !bind_texture)) { + _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); + free(surf); + return NULL; + } + /* a framebuffer of zero width or height confuses st */ + if (width == 0 || height == 0) { + _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); + free(surf); + return NULL; + } + /* no mipmap generation */ + if (surf->Base.MipmapTexture) { + _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); + free(surf); + return NULL; + } + + surf->winsys = xdpy->winsys; + + _eglConfigToContextModesRec(conf, &visual); + + /* Create GL statetracker framebuffer */ + surf->Framebuffer = st_create_framebuffer(&visual, + choose_color_format(&visual), + choose_depth_format(&visual), + choose_stencil_format(&visual), + width, height, + (void *) surf); + st_resize_framebuffer(surf->Framebuffer, width, height); + + return &surf->Base; } static EGLBoolean -xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +xlib_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) { struct xlib_egl_surface *surf = lookup_surface(surface); - if (surf) { - _eglUnlinkSurface(&surf->Base); - if (!surf->Base.IsBound) { + if (!_eglIsSurfaceBound(&surf->Base)) { + if (surf->Base.Type != EGL_PBUFFER_BIT) XFreeGC(surf->Dpy, surf->Gc); - st_unreference_framebuffer(surf->Framebuffer); - free(surf); - } - return EGL_TRUE; + st_unreference_framebuffer(surf->Framebuffer); + free(surf); } - else { - _eglError(EGL_BAD_SURFACE, "eglDestroySurface"); - return EGL_FALSE; + return EGL_TRUE; +} + + +static EGLBoolean +xlib_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *surface, EGLint buffer) +{ + struct xlib_egl_surface *xsurf = lookup_surface(surface); + struct xlib_egl_context *xctx; + struct pipe_surface *psurf; + enum pipe_format format; + int target; + + if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT) + return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); + if (xsurf->Base.BoundToTexture) + return _eglError(EGL_BAD_ACCESS, "eglBindTexImage"); + + /* this should be updated when choose_color_format is */ + switch (xsurf->Base.TextureFormat) { + case EGL_TEXTURE_RGB: + format = PIPE_FORMAT_R8G8B8_UNORM; + break; + case EGL_TEXTURE_RGBA: + format = PIPE_FORMAT_A8R8G8B8_UNORM; + break; + default: + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + } + + switch (xsurf->Base.TextureTarget) { + case EGL_TEXTURE_2D: + target = ST_TEXTURE_2D; + break; + default: + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + } + + /* flush properly */ + if (eglGetCurrentSurface(EGL_DRAW) == surface) { + xctx = lookup_context(_eglGetCurrentContext()); + st_flush(xctx->Context, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, + NULL); + } + else if (_eglIsSurfaceBound(&xsurf->Base)) { + xctx = lookup_context(xsurf->Base.Binding); + if (xctx) + st_finish(xctx->Context); } + + st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT, + &psurf); + st_bind_texture_surface(psurf, target, xsurf->Base.MipmapLevel, format); + xsurf->Base.BoundToTexture = EGL_TRUE; + + return EGL_TRUE; +} + + +static EGLBoolean +xlib_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, + EGLint buffer) +{ + struct xlib_egl_surface *xsurf = lookup_surface(surface); + struct pipe_surface *psurf; + + if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT || + !xsurf->Base.BoundToTexture) + return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); + + st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT, + &psurf); + st_unbind_texture_surface(psurf, ST_TEXTURE_2D, xsurf->Base.MipmapLevel); + xsurf->Base.BoundToTexture = EGL_FALSE; + + return EGL_TRUE; } static EGLBoolean -xlib_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +xlib_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw) { /* error checking step: */ if (!_eglSwapBuffers(drv, dpy, draw)) @@ -605,12 +816,20 @@ find_supported_apis(void) } +static void +xlib_Unload(_EGLDriver *drv) +{ + struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); + free(xdrv); +} + + /** * This is the main entrypoint into the driver. * Called by libEGL to instantiate an _EGLDriver object. */ _EGLDriver * -_eglMain(_EGLDisplay *dpy, const char *args) +_eglMain(const char *args) { struct xlib_egl_driver *xdrv; @@ -620,10 +839,6 @@ _eglMain(_EGLDisplay *dpy, const char *args) if (!xdrv) return NULL; - if (!dpy->Xdpy) { - dpy->Xdpy = XOpenDisplay(NULL); - } - _eglInitDriverFallbacks(&xdrv->Base); xdrv->Base.API.Initialize = xlib_eglInitialize; xdrv->Base.API.Terminate = xlib_eglTerminate; @@ -631,27 +846,24 @@ _eglMain(_EGLDisplay *dpy, const char *args) xdrv->Base.API.CreateContext = xlib_eglCreateContext; xdrv->Base.API.DestroyContext = xlib_eglDestroyContext; xdrv->Base.API.CreateWindowSurface = xlib_eglCreateWindowSurface; + xdrv->Base.API.CreatePbufferSurface = xlib_eglCreatePbufferSurface; xdrv->Base.API.DestroySurface = xlib_eglDestroySurface; + xdrv->Base.API.BindTexImage = xlib_eglBindTexImage; + xdrv->Base.API.ReleaseTexImage = xlib_eglReleaseTexImage; xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent; xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers; - xdrv->Base.ClientAPIsMask = find_supported_apis(); - if (xdrv->Base.ClientAPIsMask == 0x0) { + xdrv->apis = find_supported_apis(); + if (xdrv->apis == 0x0) { /* the app isn't directly linked with any EGL-supprted APIs * (such as libGLESv2.so) so use an EGL utility to see what * APIs might be loaded dynamically on this system. */ - xdrv->Base.ClientAPIsMask = _eglFindAPIs(); - } + xdrv->apis = _eglFindAPIs(); + } xdrv->Base.Name = "Xlib/softpipe"; - - /* create one winsys and use it for all contexts/surfaces */ - xdrv->winsys = create_sw_winsys(); - xdrv->winsys->flush_frontbuffer = flush_frontbuffer; - - xdrv->screen = softpipe_create_screen(xdrv->winsys); + xdrv->Base.Unload = xlib_Unload; return &xdrv->Base; } - diff --git a/src/gallium/winsys/egl_xlib/sw_winsys.c b/src/gallium/winsys/egl_xlib/sw_winsys.c index aa1bfa8e88..79ff2cc985 100644 --- a/src/gallium/winsys/egl_xlib/sw_winsys.c +++ b/src/gallium/winsys/egl_xlib/sw_winsys.c @@ -166,6 +166,7 @@ surface_buffer_create(struct pipe_winsys *winsys, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { const unsigned alignment = 64; diff --git a/src/gallium/winsys/g3dvl/xsp_winsys.c b/src/gallium/winsys/g3dvl/xsp_winsys.c index 698c2856a4..37d60ce540 100644 --- a/src/gallium/winsys/g3dvl/xsp_winsys.c +++ b/src/gallium/winsys/g3dvl/xsp_winsys.c @@ -105,6 +105,7 @@ static struct pipe_buffer* xsp_surface_buffer_create unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride ) { diff --git a/src/gallium/winsys/gdi/SConscript b/src/gallium/winsys/gdi/SConscript index 86eb9ef55e..f5e6d36d89 100644 --- a/src/gallium/winsys/gdi/SConscript +++ b/src/gallium/winsys/gdi/SConscript @@ -5,35 +5,39 @@ Import('*') if env['platform'] == 'windows': - env = env.Clone() + env = env.Clone() - env.Append(CPPPATH = [ - '#src/gallium/state_trackers/wgl', - ]) + env.Append(CPPPATH = [ + '#src/gallium/state_trackers/wgl', + ]) - env.Append(LIBS = [ - 'gdi32', - 'user32', - 'kernel32', - 'ws2_32', - ]) + env.Append(LIBS = [ + 'gdi32', + 'user32', + 'kernel32', + 'ws2_32', + ]) - sources = [ - 'gdi_softpipe_winsys.c', - ] - - if env['gcc']: - sources += ['#src/gallium/state_trackers/wgl/opengl32.mingw.def'] - else: - sources += ['#src/gallium/state_trackers/wgl/opengl32.def'] - - drivers = [ - trace, - softpipe, - ] + if 'llvmpipe' in env['drivers']: + sources = ['gdi_llvmpipe_winsys.c'] + drivers = [llvmpipe] + env.Tool('llvm') + elif 'softpipe' in env['drivers']: + sources = ['gdi_softpipe_winsys.c'] + drivers = [softpipe] + else: + print 'warning: softpipe or llvmpipe not selected, gdi winsys disabled' + Return() + + if env['gcc']: + sources += ['#src/gallium/state_trackers/wgl/opengl32.mingw.def'] + else: + sources += ['#src/gallium/state_trackers/wgl/opengl32.def'] + + drivers += [trace] - env.SharedLibrary( - target ='opengl32', - source = sources, - LIBS = wgl + glapi + mesa + drivers + auxiliaries + env['LIBS'], - ) + env.SharedLibrary( + target ='opengl32', + source = sources, + LIBS = wgl + glapi + mesa + drivers + auxiliaries + env['LIBS'], + ) diff --git a/src/gallium/winsys/gdi/gdi_llvmpipe_winsys.c b/src/gallium/winsys/gdi/gdi_llvmpipe_winsys.c new file mode 100644 index 0000000000..9d0daf77e9 --- /dev/null +++ b/src/gallium/winsys/gdi/gdi_llvmpipe_winsys.c @@ -0,0 +1,284 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, 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. + * + * + **************************************************************************/ + +/** + * @file + * LLVMpipe support. + * + * @author Jose Fonseca <jfonseca@vmware.com> + */ + + +#include <windows.h> + +#include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "pipe/p_inlines.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "llvmpipe/lp_winsys.h" +#include "llvmpipe/lp_texture.h" +#include "stw_winsys.h" + + +struct gdi_llvmpipe_displaytarget +{ + enum pipe_format format; + struct pipe_format_block block; + unsigned width; + unsigned height; + unsigned stride; + + unsigned size; + + void *data; + + BITMAPINFO bmi; +}; + + +/** Cast wrapper */ +static INLINE struct gdi_llvmpipe_displaytarget * +gdi_llvmpipe_displaytarget( struct llvmpipe_displaytarget *buf ) +{ + return (struct gdi_llvmpipe_displaytarget *)buf; +} + + +static boolean +gdi_llvmpipe_is_displaytarget_format_supported( struct llvmpipe_winsys *ws, + enum pipe_format format ) +{ + switch(format) { + case PIPE_FORMAT_X8R8G8B8_UNORM: + case PIPE_FORMAT_A8R8G8B8_UNORM: + return TRUE; + + /* TODO: Support other formats possible with BMPs, as described in + * http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx */ + + default: + return FALSE; + } +} + + +static void * +gdi_llvmpipe_displaytarget_map(struct llvmpipe_winsys *ws, + struct llvmpipe_displaytarget *dt, + unsigned flags ) +{ + struct gdi_llvmpipe_displaytarget *gdt = gdi_llvmpipe_displaytarget(dt); + + return gdt->data; +} + + +static void +gdi_llvmpipe_displaytarget_unmap(struct llvmpipe_winsys *ws, + struct llvmpipe_displaytarget *dt ) +{ + +} + + +static void +gdi_llvmpipe_displaytarget_destroy(struct llvmpipe_winsys *winsys, + struct llvmpipe_displaytarget *dt) +{ + struct gdi_llvmpipe_displaytarget *gdt = gdi_llvmpipe_displaytarget(dt); + + align_free(gdt->data); + FREE(gdt); +} + + +/** + * Round n up to next multiple. + */ +static INLINE unsigned +round_up(unsigned n, unsigned multiple) +{ + return (n + multiple - 1) & ~(multiple - 1); +} + + +static struct llvmpipe_displaytarget * +gdi_llvmpipe_displaytarget_create(struct llvmpipe_winsys *winsys, + enum pipe_format format, + unsigned width, unsigned height, + unsigned alignment, + unsigned *stride) +{ + struct gdi_llvmpipe_displaytarget *gdt; + unsigned cpp; + unsigned bpp; + + gdt = CALLOC_STRUCT(gdi_llvmpipe_displaytarget); + if(!gdt) + goto no_gdt; + + gdt->format = format; + gdt->width = width; + gdt->height = height; + + bpp = pf_get_bits(format); + cpp = pf_get_size(format); + + gdt->stride = round_up(width * cpp, alignment); + gdt->size = gdt->stride * height; + + gdt->data = align_malloc(gdt->size, alignment); + if(!gdt->data) + goto no_data; + + gdt->bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + gdt->bmi.bmiHeader.biWidth = gdt->stride / cpp; + gdt->bmi.bmiHeader.biHeight= -(long)height; + gdt->bmi.bmiHeader.biPlanes = 1; + gdt->bmi.bmiHeader.biBitCount = bpp; + gdt->bmi.bmiHeader.biCompression = BI_RGB; + gdt->bmi.bmiHeader.biSizeImage = 0; + gdt->bmi.bmiHeader.biXPelsPerMeter = 0; + gdt->bmi.bmiHeader.biYPelsPerMeter = 0; + gdt->bmi.bmiHeader.biClrUsed = 0; + gdt->bmi.bmiHeader.biClrImportant = 0; + + *stride = gdt->stride; + return (struct llvmpipe_displaytarget *)gdt; + +no_data: + FREE(gdt); +no_gdt: + return NULL; +} + + +static void +gdi_llvmpipe_displaytarget_display(struct llvmpipe_winsys *winsys, + struct llvmpipe_displaytarget *dt, + void *context_private) +{ + assert(0); +} + + +static void +gdi_llvmpipe_destroy(struct llvmpipe_winsys *winsys) +{ + FREE(winsys); +} + + +static struct pipe_screen * +gdi_llvmpipe_screen_create(void) +{ + static struct llvmpipe_winsys *winsys; + struct pipe_screen *screen; + + winsys = CALLOC_STRUCT(llvmpipe_winsys); + if(!winsys) + goto no_winsys; + + winsys->destroy = gdi_llvmpipe_destroy; + winsys->is_displaytarget_format_supported = gdi_llvmpipe_is_displaytarget_format_supported; + winsys->displaytarget_create = gdi_llvmpipe_displaytarget_create; + winsys->displaytarget_map = gdi_llvmpipe_displaytarget_map; + winsys->displaytarget_unmap = gdi_llvmpipe_displaytarget_unmap; + winsys->displaytarget_display = gdi_llvmpipe_displaytarget_display; + winsys->displaytarget_destroy = gdi_llvmpipe_displaytarget_destroy; + + screen = llvmpipe_create_screen(winsys); + if(!screen) + goto no_screen; + + return screen; + +no_screen: + FREE(winsys); +no_winsys: + return NULL; +} + + +static struct pipe_context * +gdi_llvmpipe_context_create(struct pipe_screen *screen) +{ + return llvmpipe_create(screen); +} + + +static void +gdi_llvmpipe_flush_frontbuffer(struct pipe_screen *screen, + struct pipe_surface *surface, + HDC hDC) +{ + struct llvmpipe_texture *texture; + struct gdi_llvmpipe_displaytarget *gdt; + + texture = llvmpipe_texture(surface->texture); + gdt = gdi_llvmpipe_displaytarget(texture->dt); + + StretchDIBits(hDC, + 0, 0, gdt->width, gdt->height, + 0, 0, gdt->width, gdt->height, + gdt->data, &gdt->bmi, 0, SRCCOPY); +} + + +static const struct stw_winsys stw_winsys = { + &gdi_llvmpipe_screen_create, + &gdi_llvmpipe_context_create, + &gdi_llvmpipe_flush_frontbuffer +}; + + +BOOL WINAPI +DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + if (!stw_init(&stw_winsys)) { + return FALSE; + } + return stw_init_thread(); + + case DLL_THREAD_ATTACH: + return stw_init_thread(); + + case DLL_THREAD_DETACH: + stw_cleanup_thread(); + break; + + case DLL_PROCESS_DETACH: + stw_cleanup_thread(); + stw_cleanup(); + break; + } + return TRUE; +} diff --git a/src/gallium/winsys/gdi/gdi_softpipe_winsys.c b/src/gallium/winsys/gdi/gdi_softpipe_winsys.c index 33826524d7..d82c8d6773 100644 --- a/src/gallium/winsys/gdi/gdi_softpipe_winsys.c +++ b/src/gallium/winsys/gdi/gdi_softpipe_winsys.c @@ -46,7 +46,7 @@ #include "util/u_memory.h" #include "softpipe/sp_winsys.h" #include "softpipe/sp_texture.h" -#include "shared/stw_winsys.h" +#include "stw_winsys.h" struct gdi_softpipe_buffer @@ -166,6 +166,7 @@ gdi_softpipe_surface_buffer_create(struct pipe_winsys *winsys, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { const unsigned alignment = 64; diff --git a/src/gallium/winsys/xlib/Makefile b/src/gallium/winsys/xlib/Makefile index 522f6dc5ae..3a1945d92c 100644 --- a/src/gallium/winsys/xlib/Makefile +++ b/src/gallium/winsys/xlib/Makefile @@ -34,6 +34,7 @@ XLIB_WINSYS_SOURCES = \ xlib_brw_aub.c \ xlib_brw_context.c \ xlib_brw_screen.c \ + xlib_llvmpipe.c \ xlib_softpipe.c \ xlib_trace.c diff --git a/src/gallium/winsys/xlib/SConscript b/src/gallium/winsys/xlib/SConscript index 0fb4b50f63..467d595d33 100644 --- a/src/gallium/winsys/xlib/SConscript +++ b/src/gallium/winsys/xlib/SConscript @@ -5,7 +5,7 @@ Import('*') if env['platform'] == 'linux' \ and 'mesa' in env['statetrackers'] \ - and ('softpipe' or 'i915simple' or 'trace') in env['drivers'] \ + and set(('softpipe', 'llvmpipe', 'i915simple', 'trace')).intersection(env['drivers']) \ and not env['dri']: env = env.Clone() @@ -29,6 +29,14 @@ if env['platform'] == 'linux' \ sources += ['xlib_softpipe.c'] drivers += [softpipe] + if 'llvmpipe' in env['drivers']: + env.Tool('llvm') + if 'LLVM_VERSION' in env: + env.Append(CPPDEFINES = 'GALLIUM_LLVMPIPE') + env.Tool('udis86') + sources += ['xlib_llvmpipe.c'] + drivers += [llvmpipe] + if 'i965simple' in env['drivers']: env.Append(CPPDEFINES = 'GALLIUM_I965SIMPLE') sources += [ diff --git a/src/gallium/winsys/xlib/xlib.c b/src/gallium/winsys/xlib/xlib.c index da72228215..4b71cf7ec3 100644 --- a/src/gallium/winsys/xlib/xlib.c +++ b/src/gallium/winsys/xlib/xlib.c @@ -45,6 +45,7 @@ enum mode { MODE_TRACE, MODE_BRW, MODE_CELL, + MODE_LLVMPIPE, MODE_SOFTPIPE }; @@ -62,7 +63,11 @@ static enum mode get_mode() return MODE_CELL; #endif +#if defined(GALLIUM_LLVMPIPE) + return MODE_LLVMPIPE; +#else return MODE_SOFTPIPE; +#endif } static void _init( void ) __attribute__((constructor)); @@ -87,6 +92,11 @@ static void _init( void ) xmesa_set_driver( &xlib_cell_driver ); #endif break; + case MODE_LLVMPIPE: +#if defined(GALLIUM_LLVMPIPE) + xmesa_set_driver( &xlib_llvmpipe_driver ); +#endif + break; case MODE_SOFTPIPE: #if defined(GALLIUM_SOFTPIPE) xmesa_set_driver( &xlib_softpipe_driver ); diff --git a/src/gallium/winsys/xlib/xlib.h b/src/gallium/winsys/xlib/xlib.h index d602ab0b13..347d45f4d6 100644 --- a/src/gallium/winsys/xlib/xlib.h +++ b/src/gallium/winsys/xlib/xlib.h @@ -7,6 +7,7 @@ extern struct xm_driver xlib_trace_driver; extern struct xm_driver xlib_softpipe_driver; +extern struct xm_driver xlib_llvmpipe_driver; extern struct xm_driver xlib_cell_driver; extern struct xm_driver xlib_brw_driver; diff --git a/src/gallium/winsys/xlib/xlib_brw_screen.c b/src/gallium/winsys/xlib/xlib_brw_screen.c index fe8dfff767..ef545796f3 100644 --- a/src/gallium/winsys/xlib/xlib_brw_screen.c +++ b/src/gallium/winsys/xlib/xlib_brw_screen.c @@ -249,6 +249,7 @@ aub_i915_surface_buffer_create(struct pipe_winsys *winsys, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { const unsigned alignment = 64; @@ -364,7 +365,7 @@ void xlib_brw_buffer_subdata_typed( struct pipe_winsys *pws, unsigned data_type ) { unsigned aub_type = DW_GENERAL_STATE; - unsigned aub_sub_type; + unsigned aub_sub_type = 0; switch (data_type) { case BRW_CC_VP: diff --git a/src/gallium/winsys/xlib/xlib_llvmpipe.c b/src/gallium/winsys/xlib/xlib_llvmpipe.c new file mode 100644 index 0000000000..3dd15e099b --- /dev/null +++ b/src/gallium/winsys/xlib/xlib_llvmpipe.c @@ -0,0 +1,464 @@ +/************************************************************************** + * + * 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 + */ + + +#if defined(GALLIUM_LLVMPIPE) + +#include "xm_api.h" + +#undef ASSERT +#undef Elements + +#include "pipe/internal/p_winsys_screen.h" +#include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "pipe/p_inlines.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "llvmpipe/lp_winsys.h" +#include "llvmpipe/lp_texture.h" + +#include "xlib.h" + +/** + * Subclass of pipe_buffer for Xlib winsys. + * Low-level OS/window system memory buffer + */ +struct xm_displaytarget +{ + enum pipe_format format; + struct pipe_format_block block; + unsigned width; + unsigned height; + unsigned stride; + + void *data; + void *mapped; + + XImage *tempImage; +#ifdef USE_XSHM + int shm; + XShmSegmentInfo shminfo; +#endif +}; + + +/** + * Subclass of llvmpipe_winsys for Xlib winsys + */ +struct xmesa_llvmpipe_winsys +{ + struct llvmpipe_winsys base; +/* struct xmesa_visual *xm_visual; */ +}; + + + +/** Cast wrapper */ +static INLINE struct xm_displaytarget * +xm_displaytarget( struct llvmpipe_displaytarget *dt ) +{ + return (struct xm_displaytarget *)dt; +} + + +/** + * X Shared Memory Image extension code + */ + +#ifdef USE_XSHM + +static volatile int mesaXErrorFlag = 0; + +/** + * Catches potential Xlib errors. + */ +static int +mesaHandleXError(Display *dpy, XErrorEvent *event) +{ + (void) dpy; + (void) event; + mesaXErrorFlag = 1; + return 0; +} + + +static char *alloc_shm(struct xm_displaytarget *buf, unsigned size) +{ + XShmSegmentInfo *const shminfo = & buf->shminfo; + + shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777); + if (shminfo->shmid < 0) { + return NULL; + } + + shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); + if (shminfo->shmaddr == (char *) -1) { + shmctl(shminfo->shmid, IPC_RMID, 0); + return NULL; + } + + shminfo->readOnly = False; + return shminfo->shmaddr; +} + + +/** + * Allocate a shared memory XImage back buffer for the given XMesaBuffer. + */ +static void +alloc_shm_ximage(struct xm_displaytarget *xm_buffer, + struct xmesa_buffer *xmb, + unsigned width, unsigned height) +{ + /* + * We have to do a _lot_ of error checking here to be sure we can + * really use the XSHM extension. It seems different servers trigger + * errors at different points if the extension won't work. Therefore + * we have to be very careful... + */ + int (*old_handler)(Display *, XErrorEvent *); + + xm_buffer->tempImage = XShmCreateImage(xmb->xm_visual->display, + xmb->xm_visual->visinfo->visual, + xmb->xm_visual->visinfo->depth, + ZPixmap, + NULL, + &xm_buffer->shminfo, + width, height); + if (xm_buffer->tempImage == NULL) { + xm_buffer->shm = 0; + return; + } + + + mesaXErrorFlag = 0; + old_handler = XSetErrorHandler(mesaHandleXError); + /* This may trigger the X protocol error we're ready to catch: */ + XShmAttach(xmb->xm_visual->display, &xm_buffer->shminfo); + XSync(xmb->xm_visual->display, False); + + if (mesaXErrorFlag) { + /* we are on a remote display, this error is normal, don't print it */ + XFlush(xmb->xm_visual->display); + mesaXErrorFlag = 0; + XDestroyImage(xm_buffer->tempImage); + xm_buffer->tempImage = NULL; + xm_buffer->shm = 0; + (void) XSetErrorHandler(old_handler); + return; + } + + xm_buffer->shm = 1; +} + +#endif /* USE_XSHM */ + +static boolean +xm_is_displaytarget_format_supported( struct llvmpipe_winsys *ws, + enum pipe_format format ) +{ + /* TODO: check visuals or other sensible thing here */ + return TRUE; +} + + +static void * +xm_displaytarget_map(struct llvmpipe_winsys *ws, + struct llvmpipe_displaytarget *dt, + unsigned flags) +{ + struct xm_displaytarget *xm_dt = xm_displaytarget(dt); + xm_dt->mapped = xm_dt->data; + return xm_dt->mapped; +} + +static void +xm_displaytarget_unmap(struct llvmpipe_winsys *ws, + struct llvmpipe_displaytarget *dt) +{ + struct xm_displaytarget *xm_dt = xm_displaytarget(dt); + xm_dt->mapped = NULL; +} + +static void +xm_displaytarget_destroy(struct llvmpipe_winsys *ws, + struct llvmpipe_displaytarget *dt) +{ + struct xm_displaytarget *xm_dt = xm_displaytarget(dt); + + if (xm_dt->data) { +#ifdef USE_XSHM + if (xm_dt->shminfo.shmid >= 0) { + shmdt(xm_dt->shminfo.shmaddr); + shmctl(xm_dt->shminfo.shmid, IPC_RMID, 0); + + xm_dt->shminfo.shmid = -1; + xm_dt->shminfo.shmaddr = (char *) -1; + } + else +#endif + FREE(xm_dt->data); + } + + FREE(xm_dt); +} + + +/** + * Display/copy the image in the surface into the X window specified + * by the XMesaBuffer. + */ +static void +xm_llvmpipe_display(struct xmesa_buffer *xm_buffer, + struct llvmpipe_displaytarget *dt) +{ + XImage *ximage; + struct xm_displaytarget *xm_dt = xm_displaytarget(dt); + static boolean no_swap = 0; + static boolean firsttime = 1; + + if (firsttime) { + no_swap = getenv("SP_NO_RAST") != NULL; + firsttime = 0; + } + + if (no_swap) + return; + +#ifdef USE_XSHM + if (xm_dt->shm) + { + if (xm_dt->tempImage == NULL) + { + assert(xm_dt->block.width == 1); + assert(xm_dt->block.height == 1); + alloc_shm_ximage(xm_dt, xm_buffer, + xm_dt->stride / xm_dt->block.size, + xm_dt->height); + } + + ximage = xm_dt->tempImage; + ximage->data = xm_dt->data; + + /* _debug_printf("XSHM\n"); */ + XShmPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc, + ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height, False); + } + else +#endif + { + /* display image in Window */ + ximage = xm_dt->tempImage; + ximage->data = xm_dt->data; + + /* check that the XImage has been previously initialized */ + assert(ximage->format); + assert(ximage->bitmap_unit); + + /* update XImage's fields */ + ximage->width = xm_dt->width; + ximage->height = xm_dt->height; + ximage->bytes_per_line = xm_dt->stride; + + /* _debug_printf("XPUT\n"); */ + XPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc, + ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height); + } +} + +/** + * Display/copy the image in the surface into the X window specified + * by the XMesaBuffer. + */ +static void +xm_displaytarget_display(struct llvmpipe_winsys *ws, + struct llvmpipe_displaytarget *dt, + void *context_private) +{ + XMesaContext xmctx = (XMesaContext) context_private; + struct xmesa_buffer *xm_buffer = xmctx->xm_buffer; + xm_llvmpipe_display(xm_buffer, dt); +} + + +static struct llvmpipe_displaytarget * +xm_displaytarget_create(struct llvmpipe_winsys *winsys, + enum pipe_format format, + unsigned width, unsigned height, + unsigned alignment, + unsigned *stride) +{ + struct xm_displaytarget *xm_dt = CALLOC_STRUCT(xm_displaytarget); + unsigned nblocksx, nblocksy, size; + + xm_dt = CALLOC_STRUCT(xm_displaytarget); + if(!xm_dt) + goto no_xm_dt; + + xm_dt->format = format; + xm_dt->width = width; + xm_dt->height = height; + + pf_get_block(format, &xm_dt->block); + nblocksx = pf_get_nblocksx(&xm_dt->block, width); + nblocksy = pf_get_nblocksy(&xm_dt->block, height); + xm_dt->stride = align(nblocksx * xm_dt->block.size, alignment); + size = xm_dt->stride * nblocksy; + +#ifdef USE_XSHM + if (!debug_get_bool_option("XLIB_NO_SHM", FALSE)) + { + xm_dt->shminfo.shmid = -1; + xm_dt->shminfo.shmaddr = (char *) -1; + xm_dt->shm = TRUE; + + xm_dt->data = alloc_shm(xm_dt, size); + if(!xm_dt->data) + goto no_data; + } +#endif + + if(!xm_dt->data) { + xm_dt->data = align_malloc(size, alignment); + if(!xm_dt->data) + goto no_data; + } + + *stride = xm_dt->stride; + return (struct llvmpipe_displaytarget *)xm_dt; + +no_data: + FREE(xm_dt); +no_xm_dt: + return NULL; +} + + +static void +xm_destroy( struct llvmpipe_winsys *ws ) +{ + FREE(ws); +} + + +static struct llvmpipe_winsys * +xlib_create_llvmpipe_winsys( void ) +{ + struct xmesa_llvmpipe_winsys *ws; + + ws = CALLOC_STRUCT(xmesa_llvmpipe_winsys); + if (!ws) + return NULL; + + ws->base.destroy = xm_destroy; + + ws->base.is_displaytarget_format_supported = xm_is_displaytarget_format_supported; + + ws->base.displaytarget_create = xm_displaytarget_create; + ws->base.displaytarget_map = xm_displaytarget_map; + ws->base.displaytarget_unmap = xm_displaytarget_unmap; + ws->base.displaytarget_destroy = xm_displaytarget_destroy; + + ws->base.displaytarget_display = xm_displaytarget_display; + + return &ws->base; +} + + +static struct pipe_screen * +xlib_create_llvmpipe_screen( void ) +{ + struct llvmpipe_winsys *winsys; + struct pipe_screen *screen; + + winsys = xlib_create_llvmpipe_winsys(); + if (winsys == NULL) + return NULL; + + screen = llvmpipe_create_screen(winsys); + if (screen == NULL) + goto fail; + + return screen; + +fail: + if (winsys) + winsys->destroy( winsys ); + + return NULL; +} + + +static struct pipe_context * +xlib_create_llvmpipe_context( struct pipe_screen *screen, + void *context_private ) +{ + struct pipe_context *pipe; + + pipe = llvmpipe_create(screen); + if (pipe == NULL) + goto fail; + + pipe->priv = context_private; + return pipe; + +fail: + /* Free stuff here */ + return NULL; +} + + +static void +xlib_llvmpipe_display_surface(struct xmesa_buffer *xm_buffer, + struct pipe_surface *surf) +{ + struct llvmpipe_texture *texture = llvmpipe_texture(surf->texture); + + assert(texture->dt); + if (texture->dt) + xm_llvmpipe_display(xm_buffer, texture->dt); +} + + +struct xm_driver xlib_llvmpipe_driver = +{ + .create_pipe_screen = xlib_create_llvmpipe_screen, + .create_pipe_context = xlib_create_llvmpipe_context, + .display_surface = xlib_llvmpipe_display_surface +}; + + + +#endif /* GALLIUM_LLVMPIPE */ diff --git a/src/gallium/winsys/xlib/xlib_softpipe.c b/src/gallium/winsys/xlib/xlib_softpipe.c index 1de93c4e8c..260b39e2a0 100644 --- a/src/gallium/winsys/xlib/xlib_softpipe.c +++ b/src/gallium/winsys/xlib/xlib_softpipe.c @@ -301,6 +301,7 @@ xm_flush_frontbuffer(struct pipe_winsys *pws, */ XMesaContext xmctx = (XMesaContext) context_private; xlib_softpipe_display_surface(xmctx->xm_buffer, surf); + xmesa_check_and_update_buffer_size(xmctx, xmctx->xm_buffer); } @@ -355,6 +356,7 @@ xm_surface_buffer_create(struct pipe_winsys *winsys, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { const unsigned alignment = 64; |