diff options
Diffstat (limited to 'src/mesa/drivers/dri/nouveau/nouveau_mem.c')
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_mem.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_mem.c b/src/mesa/drivers/dri/nouveau/nouveau_mem.c new file mode 100644 index 00000000000..35c53268b06 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_mem.c @@ -0,0 +1,144 @@ +#include "mtypes.h" + +#include "nouveau_context.h" +#include "nouveau_fifo.h" +#include "nouveau_mem.h" +#include "nouveau_msg.h" +#include "nouveau_object.h" +#include "nouveau_reg.h" + +#define MAX_MEMFMT_LENGTH 32768 + +/* Unstrided blit using NV_MEMORY_TO_MEMORY_FORMAT */ +GLboolean +nouveau_memformat_flat_emit(GLcontext * ctx, + nouveau_mem * dst, nouveau_mem * src, + GLuint dst_offset, GLuint src_offset, + GLuint size) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + uint32_t src_handle, dst_handle; + GLuint count; + + if (src_offset + size > src->size) { + MESSAGE("src out of nouveau_mem bounds\n"); + return GL_FALSE; + } + if (dst_offset + size > dst->size) { + MESSAGE("dst out of nouveau_mem bounds\n"); + return GL_FALSE; + } + + src_handle = (src->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaTT; + dst_handle = (dst->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaTT; + src_offset += nouveau_mem_gpu_offset_get(ctx, src); + dst_offset += nouveau_mem_gpu_offset_get(ctx, dst); + + BEGIN_RING_SIZE(NvSubMemFormat, + NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN, 2); + OUT_RING(src_handle); + OUT_RING(dst_handle); + + count = (size / MAX_MEMFMT_LENGTH) + + ((size % MAX_MEMFMT_LENGTH) ? 1 : 0); + + while (count--) { + GLuint length = + (size > MAX_MEMFMT_LENGTH) ? MAX_MEMFMT_LENGTH : size; + + BEGIN_RING_SIZE(NvSubMemFormat, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + OUT_RING(src_offset); + OUT_RING(dst_offset); + OUT_RING(0); /* pitch in */ + OUT_RING(0); /* pitch out */ + OUT_RING(length); /* line length */ + OUT_RING(1); /* number of lines */ + OUT_RING((1 << 8) /* dst_inc */ |(1 << 0) /* src_inc */ ); + OUT_RING(0); /* buffer notify? */ + FIRE_RING(); + + src_offset += length; + dst_offset += length; + size -= length; + } + + return GL_TRUE; +} + +void nouveau_mem_free(GLcontext * ctx, nouveau_mem * mem) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + struct drm_nouveau_mem_free memf; + + if (NOUVEAU_DEBUG & DEBUG_MEM) { + fprintf(stderr, "%s: type=0x%x, offset=0x%x, size=0x%x\n", + __func__, mem->type, (GLuint) mem->offset, + (GLuint) mem->size); + } + + if (mem->map) + drmUnmap(mem->map, mem->size); + memf.flags = mem->type; + memf.offset = mem->offset; + drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_MEM_FREE, &memf, + sizeof(memf)); + FREE(mem); +} + +nouveau_mem *nouveau_mem_alloc(GLcontext *ctx, uint32_t flags, GLuint size, + GLuint align) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + struct drm_nouveau_mem_alloc mema; + nouveau_mem *mem; + int ret; + + if (NOUVEAU_DEBUG & DEBUG_MEM) { + fprintf(stderr, + "%s: requested: flags=0x%x, size=0x%x, align=0x%x\n", + __func__, flags, (GLuint) size, align); + } + + mem = CALLOC(sizeof(nouveau_mem)); + if (!mem) + return NULL; + + mema.flags = flags; + mema.size = mem->size = size; + mema.alignment = align; + mem->map = NULL; + ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_MEM_ALLOC, + &mema, sizeof(mema)); + if (ret) { + FREE(mem); + return NULL; + } + mem->offset = mema.offset; + mem->type = mema.flags; + + if (NOUVEAU_DEBUG & DEBUG_MEM) { + fprintf(stderr, + "%s: actual: type=0x%x, offset=0x%x, size=0x%x\n", + __func__, mem->type, (GLuint) mem->offset, + (GLuint) mem->size); + } + + if (flags & NOUVEAU_MEM_MAPPED) + ret = drmMap(nmesa->driFd, mema.map_handle, mem->size, + &mem->map); + if (ret) { + mem->map = NULL; + nouveau_mem_free(ctx, mem); + mem = NULL; + } + + return mem; +} + +uint32_t nouveau_mem_gpu_offset_get(GLcontext * ctx, nouveau_mem * mem) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + return mem->offset; +} |