Commit 52054b6a authored by Li Shao Hua's avatar Li Shao Hua Committed by Nan Hai Zou

switch XvMC to gem

parent b6228604
......@@ -66,6 +66,7 @@ struct hwmc_buffer
struct _intel_xvmc_common {
unsigned int type;
struct hwmc_buffer batchbuffer;
unsigned int kernel_exec_fencing:1;
};
/* Intel private XvMC command to DDX driver */
......@@ -76,7 +77,7 @@ struct intel_xvmc_command {
unsigned int subPicNo;
unsigned int flags;
unsigned int real_id;
unsigned int surf_offset;
uint32_t handle;
unsigned int pad[5];
};
......
......@@ -38,6 +38,7 @@
#define _INTEL_XVMC_SERVER_
#include "i830_hwmc.h"
#include "i965_hwmc.h"
#include "intel_bufmgr.h"
#define STRIDE(w) (w)
#define SIZE_YUV420(w, h) (h * (STRIDE(w) + STRIDE(w >> 1)))
......@@ -50,40 +51,6 @@
static PutImageFuncPtr XvPutImage;
static int alloc_drm_memory(ScrnInfoPtr pScrn,
struct drm_memory_block *mem,
char *name, size_t size)
{
I830Ptr pI830 = I830PTR(pScrn);
if ((mem->buffer = i830_allocate_memory(pScrn,
name, size, PITCH_NONE, GTT_PAGE_SIZE,
ALIGN_BOTH_ENDS, TILE_NONE)) == NULL) {
ErrorF("Fail to alloc \n");
return BadAlloc;
}
if (drmAddMap(pI830->drmSubFD,
(drm_handle_t)(mem->buffer->offset + pI830->LinearAddr),
size, DRM_AGP, 0,
(drmAddress)&mem->handle) < 0) {
ErrorF("Fail to map %d \n", errno);
i830_free_memory(pScrn, mem->buffer);
return BadAlloc;
}
mem->size = size;
mem->offset = mem->buffer->offset;
return Success;
}
static void free_drm_memory(ScrnInfoPtr pScrn,
struct drm_memory_block *mem)
{
I830Ptr pI830 = I830PTR(pScrn);
drmRmMap(pI830->drmSubFD, mem->handle);
i830_free_memory(pScrn, mem->buffer);
}
static int create_context(ScrnInfoPtr pScrn,
XvMCContextPtr context, int *num_privates, CARD32 **private)
{
......@@ -106,31 +73,8 @@ static int create_context(ScrnInfoPtr pScrn,
private_context->is_g4x = IS_G4X(I830);
private_context->is_965_q = IS_965_Q(I830);
private_context->comm.kernel_exec_fencing = I830->kernel_exec_fencing;
private_context->comm.type = xvmc_driver->flag;
private_context->comm.batchbuffer.offset = xvmc_driver->batch->offset;
private_context->comm.batchbuffer.size = xvmc_driver->batch->size;
private_context->comm.batchbuffer.handle = xvmc_driver->batch_handle;
if (alloc_drm_memory(pScrn, &private_context->static_buffer,
"XVMC static buffers",
I965_MC_STATIC_BUFFER_SIZE)) {
ErrorF("Unable to allocate and map static buffer for XVMC\n");
return BadAlloc;
}
if (alloc_drm_memory(pScrn, &private_context->blocks,
"XVMC blocks", blocksize)) {
ErrorF("Unable to allocate and map block buffer for XVMC\n");
return BadAlloc;
}
if (IS_G4X(I830)) {
if (alloc_drm_memory(pScrn, &private_context->slice,
"XVMC vld slice", VLD_MAX_SLICE_LEN)) {
ErrorF("Unable to allocate and vld slice buffer for XVMC\n");
return BadAlloc;
}
}
*num_privates = sizeof(*private_context)/sizeof(CARD32);
*private = (CARD32 *)private_context;
......@@ -143,12 +87,7 @@ static int create_context(ScrnInfoPtr pScrn,
static void destroy_context(ScrnInfoPtr pScrn, XvMCContextPtr context)
{
struct i965_xvmc_context *private_context;
I830Ptr pI830 = I830PTR(pScrn);
private_context = context->driver_priv;
free_drm_memory(pScrn, &private_context->static_buffer);
free_drm_memory(pScrn, &private_context->blocks);
if (IS_G4X(pI830))
free_drm_memory(pScrn, &private_context->slice);
Xfree(private_context);
}
......@@ -159,7 +98,6 @@ static int create_surface(ScrnInfoPtr pScrn, XvMCSurfacePtr surface,
struct i965_xvmc_surface *priv_surface, *surface_dup;
struct i965_xvmc_context *priv_ctx = ctx->driver_priv;
size_t bufsize = SIZE_YUV420(ctx->width, ctx->height);
int i;
for (i = 0 ; i < I965_MAX_SURFACES; i++) {
if (priv_ctx->surfaces[i] == NULL) {
......@@ -172,13 +110,10 @@ static int create_surface(ScrnInfoPtr pScrn, XvMCSurfacePtr surface,
priv_surface->no = i;
priv_surface->handle = priv_surface;
priv_surface->w = ctx->width;
priv_surface->h = ctx->height;
priv_ctx->surfaces[i] = surface->driver_priv
= priv_surface;
if (alloc_drm_memory(pScrn, &priv_surface->buffer,
"surface buffer\n", (bufsize+0xFFF)&~(0xFFF))) {
ErrorF("Unable to allocate surface buffer\n");
return BadAlloc;
}
memcpy(surface_dup, priv_surface, sizeof(*priv_surface));
*num_priv = sizeof(*priv_surface)/sizeof(CARD32);
*priv = (CARD32 *)surface_dup;
......@@ -200,7 +135,6 @@ static void destory_surface(ScrnInfoPtr pScrn, XvMCSurfacePtr surface)
struct i965_xvmc_surface *priv_surface = surface->driver_priv;
struct i965_xvmc_context *priv_ctx = ctx->driver_priv;
priv_ctx->surfaces[priv_surface->no] = NULL;
free_drm_memory(pScrn, &priv_surface->buffer);
Xfree(priv_surface);
}
......@@ -224,21 +158,27 @@ static int put_image(ScrnInfoPtr pScrn,
{
I830Ptr pI830 = I830PTR(pScrn);
struct intel_xvmc_command *cmd = (struct intel_xvmc_command *)buf;
dri_bo *bo;
if (id == FOURCC_XVMC) {
buf = pI830->FbBase + cmd->surf_offset;
bo = intel_bo_gem_create_from_name(pI830->bufmgr, "surface", cmd->handle);
dri_bo_pin(bo, 0x1000);
buf = pI830->FbBase + bo->offset;
}
XvPutImage(pScrn, src_x, src_y, drw_x, drw_y, src_w, src_h,
drw_w, drw_h, id, buf, width, height, sync, clipBoxes,
data, pDraw);
if (id == FOURCC_XVMC) {
dri_bo_unpin(bo);
dri_bo_unreference(bo);
}
return Success;
}
static Bool init(ScrnInfoPtr screen_info, XF86VideoAdaptorPtr adaptor)
{
if (!intel_xvmc_init_batch(screen_info)) {
ErrorF("[XvMC] fail to init batch buffer\n");
return FALSE;
}
XvPutImage = adaptor->PutImage;
adaptor->PutImage = put_image;
......
......@@ -10,9 +10,10 @@ struct drm_memory_block {
};
struct i965_xvmc_surface {
struct drm_memory_block buffer;
int w, h;
unsigned int no;
void *handle;
dri_bo *bo;
};
struct i965_xvmc_context {
......
......@@ -31,4 +31,4 @@ libIntelXvMC_la_SOURCES = intel_xvmc.c \
libIntelXvMC_la_CFLAGS = @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
@XVMCLIB_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
libIntelXvMC_la_LDFLAGS = -version-number 1:0:0
libIntelXvMC_la_LIBADD = @DRI_LIBS@ @DRM_LIBS@ @XVMCLIB_LIBS@ @XEXT_LIBS@ -lpthread
libIntelXvMC_la_LIBADD = @DRI_LIBS@ @DRM_LIBS@ @XVMCLIB_LIBS@ @XEXT_LIBS@ -lpthread -ldrm_intel
This diff is collapsed.
......@@ -45,9 +45,10 @@
#include "intel_xvmc.h"
#include "intel_batchbuffer.h"
#include "brw_defines.h"
#include "brw_structs.h"
#define MI_BATCH_BUFFER_END (0xA << 23)
#define BATCH_SIZE 8*1024 /* one bo is allocated each time, so the size can be small */
static int intelEmitIrqLocked(void)
{
drmI830IrqEmit ie;
......@@ -82,192 +83,105 @@ static void intelWaitIrq(int seq)
}
}
static void intelDestroyBatchBuffer(void)
static void i965_end_batch(void)
{
if (xvmc_driver->alloc.offset) {
xvmc_driver->alloc.ptr = NULL;
xvmc_driver->alloc.offset = 0;
} else if (xvmc_driver->alloc.ptr) {
free(xvmc_driver->alloc.ptr);
xvmc_driver->alloc.ptr = NULL;
}
memset(&xvmc_driver->batch, 0, sizeof(xvmc_driver->batch));
unsigned int size = xvmc_driver->batch.ptr -
xvmc_driver->batch.init_ptr;
if ((size & 4) == 0) {
*(unsigned int*)xvmc_driver->batch.ptr = 0;
xvmc_driver->batch.ptr += 4;
}
*(unsigned int*)xvmc_driver->batch.ptr = MI_BATCH_BUFFER_END;
xvmc_driver->batch.ptr += 4;
}
Bool intelInitBatchBuffer(void)
{
if (drmMap(xvmc_driver->fd,
xvmc_driver->batchbuffer.handle,
xvmc_driver->batchbuffer.size,
(drmAddress *)&xvmc_driver->batchbuffer.map) != 0) {
XVMC_ERR("fail to map batch buffer\n");
int i;
if((xvmc_driver->batch.buf =
drm_intel_bo_alloc(xvmc_driver->bufmgr,
"batch buffer", BATCH_SIZE, 0x1000)) == NULL) {
fprintf(stderr, "unable to alloc batch buffer\n");
return False;
}
if (xvmc_driver->batchbuffer.map) {
xvmc_driver->alloc.size = xvmc_driver->batchbuffer.size;
xvmc_driver->alloc.offset = xvmc_driver->batchbuffer.offset;
xvmc_driver->alloc.ptr = xvmc_driver->batchbuffer.map;
} else {
xvmc_driver->alloc.size = 8 * 1024;
xvmc_driver->alloc.offset = 0;
xvmc_driver->alloc.ptr = malloc(xvmc_driver->alloc.size);
}
if (xvmc_driver->kernel_exec_fencing)
drm_intel_gem_bo_map_gtt(xvmc_driver->batch.buf);
else
drm_intel_bo_map(xvmc_driver->batch.buf, 1);
xvmc_driver->alloc.active_buf = 0;
assert(xvmc_driver->alloc.ptr);
xvmc_driver->batch.init_ptr = xvmc_driver->batch.buf->virtual;
xvmc_driver->batch.size = BATCH_SIZE;
xvmc_driver->batch.space = BATCH_SIZE;
xvmc_driver->batch.ptr = xvmc_driver->batch.init_ptr;
return True;
}
void intelFiniBatchBuffer(void)
{
if (xvmc_driver->batchbuffer.map) {
drmUnmap(xvmc_driver->batchbuffer.map, xvmc_driver->batchbuffer.size);
xvmc_driver->batchbuffer.map = NULL;
}
intelDestroyBatchBuffer();
}
static void intelBatchbufferRequireSpace(unsigned int sz)
{
if (xvmc_driver->batch.space < sz)
intelFlushBatch(TRUE);
}
void intelBatchbufferData(const void *data, unsigned bytes, unsigned flags)
{
assert((bytes & 0x3) == 0);
intelBatchbufferRequireSpace(bytes);
memcpy(xvmc_driver->batch.ptr, data, bytes);
xvmc_driver->batch.ptr += bytes;
xvmc_driver->batch.space -= bytes;
if (xvmc_driver->kernel_exec_fencing)
drm_intel_gem_bo_unmap_gtt(xvmc_driver->batch.buf);
else
drm_intel_bo_unmap(xvmc_driver->batch.buf);
assert(xvmc_driver->batch.space >= 0);
drm_intel_bo_unreference(xvmc_driver->batch.buf);
}
#define MI_FLUSH ((0 << 29) | (4 << 23))
#define FLUSH_MAP_CACHE (1 << 0)
#define FLUSH_RENDER_CACHE (0 << 2)
#define FLUSH_WRITE_DIRTY_STATE (1 << 4)
static void intelRefillBatchLocked(Bool allow_unlock)
void intelFlushBatch(Bool refill )
{
unsigned half = xvmc_driver->alloc.size >> 1;
unsigned buf = (xvmc_driver->alloc.active_buf ^= 1);
unsigned dword[2];
dword[0] = MI_FLUSH | FLUSH_WRITE_DIRTY_STATE | FLUSH_RENDER_CACHE | FLUSH_MAP_CACHE;
dword[1] = 0;
intelCmdIoctl((char *)&dword[0], sizeof(dword));
xvmc_driver->alloc.irq_emitted = intelEmitIrqLocked();
i965_end_batch();
if (xvmc_driver->kernel_exec_fencing)
drm_intel_gem_bo_unmap_gtt(xvmc_driver->batch.buf);
else
drm_intel_bo_unmap(xvmc_driver->batch.buf);
drm_intel_bo_exec(xvmc_driver->batch.buf,
xvmc_driver->batch.ptr - xvmc_driver->batch.init_ptr,
0, 0, 0);
//dri_bo_wait_rendering(xvmc_driver->batch.buf);
drm_intel_bo_unreference(xvmc_driver->batch.buf);
if((xvmc_driver->batch.buf =
drm_intel_bo_alloc(xvmc_driver->bufmgr,
"batch buffer", BATCH_SIZE, 0x1000)) == NULL) {
fprintf(stderr, "unable to alloc batch buffer\n");
}
if (xvmc_driver->alloc.irq_emitted) {
intelWaitIrq(xvmc_driver->alloc.irq_emitted);
}
if (xvmc_driver->kernel_exec_fencing)
drm_intel_gem_bo_map_gtt(xvmc_driver->batch.buf);
else
drm_intel_bo_map(xvmc_driver->batch.buf, 1);
xvmc_driver->batch.start_offset = xvmc_driver->alloc.offset + buf * half;
xvmc_driver->batch.ptr = (unsigned char *)xvmc_driver->alloc.ptr + buf * half;
xvmc_driver->batch.size = half - 8;
xvmc_driver->batch.space = half - 8;
assert(xvmc_driver->batch.space >= 0);
xvmc_driver->batch.init_ptr = xvmc_driver->batch.buf->virtual;
xvmc_driver->batch.size = BATCH_SIZE;
xvmc_driver->batch.space = BATCH_SIZE;
xvmc_driver->batch.ptr = xvmc_driver->batch.init_ptr;
}
static void intelFlushBatchLocked(Bool ignore_cliprects,
Bool refill,
Bool allow_unlock)
void intelBatchbufferRequireSpace(int size)
{
drmI830BatchBuffer batch;
if (xvmc_driver->batch.space != xvmc_driver->batch.size) {
batch.start = xvmc_driver->batch.start_offset;
batch.used = xvmc_driver->batch.size - xvmc_driver->batch.space;
batch.cliprects = 0;
batch.num_cliprects = 0;
batch.DR1 = 0;
batch.DR4 = 0;
if (xvmc_driver->alloc.offset) {
if ((batch.used & 0x4) == 0) {
((int *)xvmc_driver->batch.ptr)[0] = 0;
((int *)xvmc_driver->batch.ptr)[1] = MI_BATCH_BUFFER_END;
batch.used += 0x8;
xvmc_driver->batch.ptr += 0x8;
} else {
((int *)xvmc_driver->batch.ptr)[0] = MI_BATCH_BUFFER_END;
batch.used += 0x4;
xvmc_driver->batch.ptr += 0x4;
}
}
xvmc_driver->batch.start_offset += batch.used;
xvmc_driver->batch.size -= batch.used;
if (xvmc_driver->batch.size < 8) {
refill = TRUE;
xvmc_driver->batch.space = xvmc_driver->batch.size = 0;
}
else {
xvmc_driver->batch.size -= 8;
xvmc_driver->batch.space = xvmc_driver->batch.size;
}
assert(xvmc_driver->batch.space >= 0);
assert(batch.start >= xvmc_driver->alloc.offset);
assert(batch.start < xvmc_driver->alloc.offset + xvmc_driver->alloc.size);
assert(batch.start + batch.used > xvmc_driver->alloc.offset);
assert(batch.start + batch.used <= xvmc_driver->alloc.offset + xvmc_driver->alloc.size);
if (xvmc_driver->alloc.offset) {
if (drmCommandWrite(xvmc_driver->fd, DRM_I830_BATCHBUFFER, &batch, sizeof(batch))) {
fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno);
exit(1);
}
} else {
drmI830CmdBuffer cmd;
cmd.buf = (char *)xvmc_driver->alloc.ptr + batch.start;
cmd.sz = batch.used;
cmd.DR1 = batch.DR1;
cmd.DR4 = batch.DR4;
cmd.num_cliprects = batch.num_cliprects;
cmd.cliprects = batch.cliprects;
if (drmCommandWrite(xvmc_driver->fd, DRM_I830_CMDBUFFER,
&cmd, sizeof(cmd))) {
fprintf(stderr, "DRM_I915_CMDBUFFER: %d\n", -errno);
exit(1);
}
}
}
if (refill)
intelRefillBatchLocked(allow_unlock);
assert(xvmc_driver->batch.ptr - xvmc_driver->batch.init_ptr + size <
xvmc_driver->batch.size - 8);
if (xvmc_driver->batch.ptr - xvmc_driver->batch.init_ptr + size
>= xvmc_driver->batch.size - 8)
intelFlushBatch(1);
}
void intelFlushBatch(Bool refill )
void intelBatchbufferData(const void *data, unsigned bytes, unsigned flags)
{
intelFlushBatchLocked(FALSE, refill, TRUE);
intelBatchbufferRequireSpace(bytes);
memcpy(xvmc_driver->batch.ptr, data, bytes);
xvmc_driver->batch.ptr += bytes;
xvmc_driver->batch.space -= bytes;
}
void intelCmdIoctl(char *buf, unsigned used)
void intel_batch_emit_reloc(dri_bo *bo, uint32_t read_domain,
uint32_t write_domain, uint32_t delta, unsigned char *ptr)
{
drmI830CmdBuffer cmd;
cmd.buf = buf;
cmd.sz = used;
cmd.cliprects = 0;
cmd.num_cliprects = 0;
cmd.DR1 = 0;
cmd.DR4 = 0;
if (drmCommandWrite(xvmc_driver->fd, DRM_I830_CMDBUFFER,
&cmd, sizeof(cmd))) {
fprintf(stderr, "DRM_I830_CMDBUFFER: %d\n", -errno);
exit(1);
}
drm_intel_bo_emit_reloc(xvmc_driver->batch.buf,
ptr - xvmc_driver->batch.init_ptr, bo, delta,
read_domain, write_domain);
}
......@@ -10,6 +10,7 @@ extern int VERBOSE;
#define BEGIN_BATCH(n) \
do { \
assert(xvmc_driver->batch.space >= (n) *4); \
if (xvmc_driver->batch.space < (n)*4) \
intelFlushBatch(TRUE); \
batch_ptr = xvmc_driver->batch.ptr; \
......@@ -21,6 +22,13 @@ extern int VERBOSE;
batch_ptr += 4; \
} while (0)
#define OUT_RELOC(bo,read_domains,write_domains,delta) \
do { \
*(unsigned int *)batch_ptr = delta + bo->offset; \
intel_batch_emit_reloc(bo, read_domains, write_domains, delta, batch_ptr); \
batch_ptr += 4; \
} while (0)
#define OUT_BATCH_SHORT(n) \
do { \
*(short *)batch_ptr = (n); \
......@@ -44,4 +52,6 @@ extern void intelBatchbufferData(const void *, unsigned, unsigned);
extern Bool intelInitBatchBuffer(void);
extern void intelFiniBatchBuffer(void);
extern void intelCmdIoctl(char *, unsigned);
extern void intel_batch_emit_reloc(dri_bo *bo, uint32_t read_domain,
uint32_t write_domain, uint32_t delta, unsigned char *);
#endif /* _INTEL_BATCHBUFFER_H */
......@@ -342,9 +342,7 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
XVMC_INFO("decoder type is %s", intel_xvmc_decoder_string(comm->type));
xvmc_driver->batchbuffer.handle = comm->batchbuffer.handle;
xvmc_driver->batchbuffer.offset = comm->batchbuffer.offset;
xvmc_driver->batchbuffer.size = comm->batchbuffer.size;
xvmc_driver->kernel_exec_fencing = comm->kernel_exec_fencing;
/* assign local ctx info */
intel_ctx = intel_xvmc_new_context(display);
......@@ -410,6 +408,13 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
return ret;
}
if ((xvmc_driver->bufmgr =
intel_bufmgr_gem_init(xvmc_driver->fd, 1024*64)) == NULL) {
XVMC_ERR("Can't init bufmgr\n");
return BadAlloc;
}
drm_intel_bufmgr_gem_enable_reuse(xvmc_driver->bufmgr);
/* call driver hook.
* driver hook should free priv_data after return if success.*/
ret = (xvmc_driver->create_context)(display, context, priv_count, priv_data);
......@@ -451,6 +456,10 @@ _X_EXPORT Status XvMCDestroyContext(Display *display, XvMCContext *context)
return ret;
}
intelFiniBatchBuffer();
dri_bufmgr_destroy(xvmc_driver->bufmgr);
intel_xvmc_free_context(context->context_id);
ret = _xvmc_destroy_context(display, context);
......@@ -466,7 +475,6 @@ _X_EXPORT Status XvMCDestroyContext(Display *display, XvMCContext *context)
close(xvmc_driver->fd);
xvmc_driver->fd = -1;
intelFiniBatchBuffer();
intel_xvmc_dump_close();
}
return Success;
......
......@@ -53,8 +53,9 @@
#include <X11/extensions/XvMClib.h>
#include <X11/extensions/vldXvMC.h>
#include <drm_sarea.h>
#include "i915_drm.h"
#include "xf86dri.h"
#include "intel_bufmgr.h"
#include "intel_batchbuffer.h"
......@@ -131,11 +132,16 @@ typedef struct _intel_xvmc_driver {
int fd; /* drm file handler */
dri_bufmgr *bufmgr;
unsigned int kernel_exec_fencing:1;
struct {
unsigned int start_offset;
unsigned int init_offset;
unsigned int size;
unsigned int space;
unsigned char *ptr;
unsigned char *init_ptr;
dri_bo *buf;
} batch;
struct
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment