Commit 529f86fb authored by Jakob Bornecrantz's avatar Jakob Bornecrantz

intel: Add a none working GEM backend for intel

parent f6d09531
TOP = ../../../../../..
include $(TOP)/configs/current
LIBNAME = inteldrm
C_SOURCES = \
intel_be_batchbuffer.c \
intel_be_context.c \
intel_be_device.c
include ./Makefile.template
DRIVER_DEFINES = $(shell pkg-config libdrm --cflags \
&& pkg-config libdrm --atleast-version=2.3.1 \
&& echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP")
symlinks:
# -*-makefile-*-
# We still have a dependency on the "dri" buffer manager. Most likely
# the interface can be reused in non-dri environments, and also as a
# frontend to simpler memory managers.
#
COMMON_SOURCES =
OBJECTS = $(C_SOURCES:.c=.o) \
$(CPP_SOURCES:.cpp=.o) \
$(ASM_SOURCES:.S=.o)
### Include directories
INCLUDES = \
-I. \
-I$(TOP)/src/gallium/include \
-I$(TOP)/src/gallium/auxiliary \
-I$(TOP)/src/gallium/drivers \
-I$(TOP)/include \
$(DRIVER_INCLUDES)
##### RULES #####
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
.cpp.o:
$(CXX) -c $(INCLUDES) $(CXXFLAGS) $(DRIVER_DEFINES) $< -o $@
.S.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
##### TARGETS #####
default: depend symlinks $(LIBNAME)
$(LIBNAME): $(OBJECTS) Makefile Makefile.template
$(TOP)/bin/mklib -o $@ -static $(OBJECTS) $(DRIVER_LIBS)
depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) $(CPP_SOURCES) \
$(ASM_SOURCES) 2> /dev/null
# Emacs tags
tags:
etags `find . -name \*.[ch]` `find ../include`
# Remove .o and backup files
clean::
-rm -f *.o */*.o *~ *.so *.a *~ server/*.o $(SYMLINKS)
-rm -f depend depend.bak
include depend
#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 = 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 NULL;
}
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->base.max_relocs = INTEL_DEFAULT_RELOCS;
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);
batch->base.ptr += 4;
/*
TODO: Enable this when we submit batch buffers to HW
ret = drm_intel_bo_emit_reloc(bo, pre_add,
batch->bo, offset,
read_domains,
write_domain);
*/
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;
assert(i915_batchbuffer_space(i915) >= 0);
/* TODO: submit stuff to HW */
intel_be_batchbuffer_reset(batch);
if (fence) {
if (*fence)
intel_be_fence_unreference(*fence);
(*fence) = CALLOC_STRUCT(intel_be_fence);
(*fence)->refcount = 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);
}
#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
#include "intel_be_device.h"
#include "intel_be_context.h"
#include "intel_be_batchbuffer.h"
#include "i915_drm.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;
}
if (access_flags & I915_BUFFER_ACCESS_READ) {
read = I915_GEM_DOMAIN_SAMPLER |
I915_GEM_DOMAIN_INSTRUCTION |
I915_GEM_DOMAIN_VERTEX;
}
ret = intel_be_offset_relocation(intel->batch,
delta,
bo,
read,
write);
/* 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);
}
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->batch = intel_be_batchbuffer_alloc(intel);
return true;
}
void
intel_be_destroy_context(struct intel_be_context *intel)
{
intel_be_batchbuffer_free(intel->batch);
}
#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;
/*
* Hardware lock functions.
*
* Needs to be filled in by the winsys.
*/
void (*hardware_lock)(struct intel_be_context *context);
void (*hardware_unlock)(struct intel_be_context *context);
boolean (*hardware_locked)(struct intel_be_context *context);
};
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);
/**
* Destroy a intel_be_context.
*
* Does not free the struct that is up to the winsys.
*/
void
intel_be_destroy_context(struct intel_be_context *intel);
#endif
#include "intel_be_device.h"
#include "pipe/p_winsys.h"
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
#include "pipe/p_inlines.h"
#include "util/u_memory.h"
#include "intel_be_fence.h"
#include "i915simple/i915_screen.h"
/**
* Turn a pipe winsys into an intel/pipe winsys:
*/
static INLINE struct intel_be_device *
intel_be_device(struct pipe_winsys *winsys)
{
return (struct intel_be_device *)winsys;
}
/*
* 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_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_winsys *winsys,
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;
buffer->base.refcount = 1;
buffer->base.alignment = alignment;
buffer->base.usage = usage;
buffer->base.size = size;
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;
buffer->base.refcount = 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;
}
struct pipe_buffer *
intel_be_buffer_from_handle(struct intel_be_device *dev,
const char* name, unsigned handle)
{
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;
buffer->base.refcount = 1;
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;
}
/*
* 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;
assert(p);
if (f)
intel_be_fence_reference(f);
if (*p)
intel_be_fence_unreference(*p);
*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
*/
boolean
intel_be_init_device(struct intel_be_device *dev, int fd, unsigned id)
{
dev->fd = fd;
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_alloc = NULL;
dev->base.surface_alloc_storage = NULL;
dev->base.surface_release = 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->pools.gem = drm_intel_bufmgr_gem_init(dev->fd, dev->max_batch_size);
dev->screen = i915_create_screen(&dev->base, id);
return true;
}
void
intel_be_destroy_device(struct intel_be_device *dev)
{
drm_intel_bufmgr_destroy(dev->pools.gem);
}
#ifndef INTEL_DRM_DEVICE_H
#define INTEL_DRM_DEVICE_H
#include "pipe/p_winsys.h"
#include "pipe/p_context.h"
#include "drm.h"
#include "intel_bufmgr.h"
/*
* Device
*/
struct intel_be_device
{
struct pipe_winsys base;
/**
* Hw level screen
*/
struct pipe_screen *screen;
int fd; /**< Drm file discriptor */
size_t max_batch_size;
size_t max_vertex_size;
struct {
drm_intel_bufmgr *gem;
} pools;
};
boolean
intel_be_init_device(struct intel_be_device *device, int fd, unsigned id);
void
intel_be_destroy_device(struct intel_be_device *dev);
/*
* Buffer
*/
struct intel_be_buffer {
struct pipe_buffer base;
drm_intel_bo *bo;
};
/**
* Create a be buffer from a drm bo handle
*
* Takes a reference
*/
struct pipe_buffer *
intel_be_buffer_from_handle(struct intel_be_device *device,
const char* name, unsigned handle);
static INLINE struct intel_be_buffer *