#include "state_tracker/drm_driver.h" #include "i965_drm_winsys.h" #include "util/u_memory.h" #include "util/u_inlines.h" #include "i915_drm.h" #include "intel_bufmgr.h" const char *names[BRW_BUFFER_TYPE_MAX] = { "TEXTURE", "SCANOUT", "VERTEX", "CURBE", "QUERY", "SHADER_CONSTANTS", "WM_SCRATCH", "BATCH", "GENERAL_STATE", "SURFACE_STATE", "PIXEL", "GENERIC", }; const char *usages[BRW_USAGE_MAX] = { "STATE", "QUERY_RESULT", "RENDER_TARGET", "DEPTH_BUFFER", "BLIT_SOURCE", "BLIT_DEST", "SAMPLER", "VERTEX", "SCRATCH" }; const char *data_types[BRW_DATA_MAX] = { "GS: CC_VP", "GS: CC_UNIT", "GS: WM_PROG", "GS: SAMPLER_DEFAULT_COLOR", "GS: SAMPLER", "GS: WM_UNIT", "GS: SF_PROG", "GS: SF_VP", "GS: SF_UNIT", "GS: VS_UNIT", "GS: VS_PROG", "GS: GS_UNIT", "GS: GS_PROG", "GS: CLIP_VP", "GS: CLIP_UNIT", "GS: CLIP_PROG", "SS: SURFACE", "SS: SURF_BIND", "CONSTANT DATA", "BATCH DATA", "(untyped)" }; static enum pipe_error i965_libdrm_bo_alloc(struct brw_winsys_screen *sws, enum brw_buffer_type type, unsigned size, unsigned alignment, struct brw_winsys_buffer **bo_out) { struct i965_libdrm_winsys *idws = i965_libdrm_winsys(sws); struct i965_libdrm_buffer *buf; if (BRW_DUMP) debug_printf("%s type %s sz %d align %d\n", __FUNCTION__, names[type], size, alignment ); buf = CALLOC_STRUCT(i965_libdrm_buffer); if (!buf) return PIPE_ERROR_OUT_OF_MEMORY; switch (type) { case BRW_BUFFER_TYPE_TEXTURE: /* case BRW_BUFFER_TYPE_SCANOUT:*/ case BRW_BUFFER_TYPE_VERTEX: case BRW_BUFFER_TYPE_CURBE: case BRW_BUFFER_TYPE_QUERY: case BRW_BUFFER_TYPE_SHADER_CONSTANTS: case BRW_BUFFER_TYPE_SHADER_SCRATCH: case BRW_BUFFER_TYPE_BATCH: case BRW_BUFFER_TYPE_GENERAL_STATE: case BRW_BUFFER_TYPE_SURFACE_STATE: case BRW_BUFFER_TYPE_PIXEL: case BRW_BUFFER_TYPE_GENERIC: break; case BRW_BUFFER_TYPE_SCANOUT: buf->map_gtt = TRUE; break; default: assert(0); break; } buf->bo = drm_intel_bo_alloc(idws->gem, names[type], size, alignment); if (!buf->bo) goto err; pipe_reference_init(&buf->base.reference, 1); buf->base.size = size; buf->base.sws = sws; *bo_out = &buf->base; return PIPE_OK; err: assert(0); FREE(buf); return PIPE_ERROR_OUT_OF_MEMORY; } static enum pipe_error i965_libdrm_bo_from_handle(struct brw_winsys_screen *sws, struct winsys_handle *whandle, unsigned *stride, unsigned *tile, struct brw_winsys_buffer **bo_out) { struct i965_libdrm_winsys *idws = i965_libdrm_winsys(sws); struct i965_libdrm_buffer *buf = CALLOC_STRUCT(i965_libdrm_buffer); uint32_t swizzle = 0; if (BRW_DUMP) debug_printf("%s\n", __FUNCTION__); if (!buf) return PIPE_ERROR_OUT_OF_MEMORY; pipe_reference_init(&buf->base.reference, 1); buf->bo = drm_intel_bo_gem_create_from_name(idws->gem, "FROM_HANDLE", whandle->handle); buf->base.size = buf->bo->size; buf->base.sws = &idws->base; buf->flinked = TRUE; buf->flink = whandle->handle; if (!buf->bo) goto err; drm_intel_bo_get_tiling(buf->bo, &buf->tiling, &swizzle); if (buf->tiling != 0) buf->map_gtt = TRUE; *tile = buf->tiling; *stride = whandle->stride; *bo_out = &buf->base; return PIPE_OK; err: FREE(buf); return PIPE_ERROR_OUT_OF_MEMORY; } static enum pipe_error i965_libdrm_bo_get_handle(struct brw_winsys_buffer *buffer, struct winsys_handle *whandle, unsigned stride) { struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); if (BRW_DUMP) debug_printf("%s\n", __FUNCTION__); if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { if (!buf->flinked) { if (drm_intel_bo_flink(buf->bo, &buf->flink)) return PIPE_ERROR_BAD_INPUT; buf->flinked = TRUE; } whandle->handle = buf->flink; } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { whandle->handle = buf->bo->handle; } else { assert(!"unknown usage"); return PIPE_ERROR_BAD_INPUT; } whandle->stride = stride; return PIPE_OK; } static void i965_libdrm_bo_destroy(struct brw_winsys_buffer *buffer) { struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); if (BRW_DUMP) debug_printf("%s\n", __FUNCTION__); drm_intel_bo_unreference(buf->bo); FREE(buffer); } static enum pipe_error i965_libdrm_bo_emit_reloc(struct brw_winsys_buffer *buffer, enum brw_buffer_usage usage, unsigned delta, unsigned offset, struct brw_winsys_buffer *buffer2) { struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); struct i965_libdrm_buffer *buf2 = i965_libdrm_buffer(buffer2); int read, write; int ret; if (BRW_DUMP) debug_printf("%s buf %p offset %x delta %x buf2 %p/%s/%s\n", __FUNCTION__, (void *)buffer, offset, delta, (void *)buffer2, names[buf2->data_type], usages[usage]); switch (usage) { case BRW_USAGE_STATE: read = I915_GEM_DOMAIN_INSTRUCTION; write = 0; break; case BRW_USAGE_QUERY_RESULT: read = I915_GEM_DOMAIN_INSTRUCTION; write = I915_GEM_DOMAIN_INSTRUCTION; break; case BRW_USAGE_RENDER_TARGET: read = I915_GEM_DOMAIN_RENDER; write = 0; break; case BRW_USAGE_DEPTH_BUFFER: read = I915_GEM_DOMAIN_RENDER; write = I915_GEM_DOMAIN_RENDER; break; case BRW_USAGE_BLIT_SOURCE: read = 0; write = I915_GEM_DOMAIN_RENDER; break; case BRW_USAGE_BLIT_DEST: read = I915_GEM_DOMAIN_RENDER; write = I915_GEM_DOMAIN_RENDER; break; case BRW_USAGE_SAMPLER: read = I915_GEM_DOMAIN_SAMPLER; write = 0; break; case BRW_USAGE_VERTEX: read = I915_GEM_DOMAIN_VERTEX; write = 0; break; case BRW_USAGE_SCRATCH: read = 0; write = 0; break; default: assert(0); return -1; } /* Needed?? ((uint32_t *)buf->bo->virtual)[offset/4] = (delta + buf2->bo->offset); */ ret = dri_bo_emit_reloc( buf->bo, read, write, delta, offset, buf2->bo ); if (ret) return -1; return 0; } static enum pipe_error i965_libdrm_bo_exec(struct brw_winsys_buffer *buffer, unsigned bytes_used) { struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); struct i965_libdrm_winsys *idws = i965_libdrm_winsys(buffer->sws); int ret; if (BRW_DUMP) debug_printf("execute buffer %p, bytes %d\n", (void *)buffer, bytes_used); if (idws->send_cmd) { ret = dri_bo_exec(buf->bo, bytes_used, NULL, 0, 0); if (ret) return PIPE_ERROR; } return PIPE_OK; } static enum pipe_error i965_libdrm_bo_subdata(struct brw_winsys_buffer *buffer, enum brw_buffer_data_type data_type, size_t offset, size_t size, const void *data, const struct brw_winsys_reloc *reloc, unsigned nr_reloc) { struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); struct i965_libdrm_winsys *idws = i965_libdrm_winsys(buffer->sws); int ret, i; (void)data_type; if (BRW_DUMP) debug_printf("%s buf %p off %d sz %d %s relocs: %d\n", __FUNCTION__, (void *)buffer, offset, size, data_types[data_type], nr_reloc); if (BRW_DUMP) brw_dump_data( idws->base.pci_id, data_type, buf->bo->offset + offset, data, size, buffer->sws->gen ); /* XXX: use bo_map_gtt/memcpy/unmap_gtt under some circumstances??? */ ret = drm_intel_bo_subdata(buf->bo, offset, size, (void*)data); if (ret) return PIPE_ERROR; for (i = 0; i < nr_reloc; i++) { i965_libdrm_bo_emit_reloc(buffer, reloc[i].usage, reloc[i].delta, reloc[i].offset, reloc[i].bo); } return PIPE_OK; } static boolean i965_libdrm_bo_is_busy(struct brw_winsys_buffer *buffer) { struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); boolean ret; if (BRW_DUMP) debug_printf("%s %p\n", __FUNCTION__, (void *)buffer); ret = drm_intel_bo_busy(buf->bo); if (BRW_DUMP) debug_printf(" --> %d\n", ret); return ret; } static boolean i965_libdrm_bo_references(struct brw_winsys_buffer *a, struct brw_winsys_buffer *b) { struct i965_libdrm_buffer *bufa = i965_libdrm_buffer(a); struct i965_libdrm_buffer *bufb = i965_libdrm_buffer(b); boolean ret; if (BRW_DUMP) debug_printf("%s %p %p\n", __FUNCTION__, (void *)a, (void *)b); ret = drm_intel_bo_references(bufa->bo, bufb->bo); if (BRW_DUMP) debug_printf(" --> %d\n", ret); return ret; } /* XXX: couldn't this be handled by returning true/false on * bo_emit_reloc? */ static enum pipe_error i965_libdrm_check_aperture_space(struct brw_winsys_screen *iws, struct brw_winsys_buffer **buffers, unsigned count) { static drm_intel_bo *bos[128]; int i; int ret; if (BRW_DUMP) debug_printf("%s\n", __FUNCTION__); if (count > Elements(bos)) { assert(0); return FALSE; } for (i = 0; i < count; i++) bos[i] = i965_libdrm_buffer(buffers[i])->bo; /* XXX: converting from ??? to pipe_error: */ ret = dri_bufmgr_check_aperture_space(bos, count); if (BRW_DUMP) debug_printf(" --> %d (ok == %d)\n", ret, PIPE_OK); return ret; } static void * i965_libdrm_bo_map(struct brw_winsys_buffer *buffer, enum brw_buffer_data_type data_type, unsigned offset, unsigned length, boolean write, boolean discard, boolean flush_explicit) { struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); int ret; if (BRW_DUMP) debug_printf("%s %p %s %s\n", __FUNCTION__, (void *)buffer, write ? "read/write" : "read", write ? data_types[data_type] : ""); if (!buf->map_count) { if (buf->map_gtt) { ret = drm_intel_gem_bo_map_gtt(buf->bo); if (ret) return NULL; } else { ret = drm_intel_bo_map(buf->bo, write); if (ret) return NULL; } } buf->data_type = data_type; buf->map_count++; return buf->bo->virtual; } static void i965_libdrm_bo_flush_range(struct brw_winsys_buffer *buffer, unsigned offset, unsigned length) { struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); struct i965_libdrm_winsys *idws = i965_libdrm_winsys(buffer->sws); if (BRW_DUMP) debug_printf("%s %s offset %d len %d\n", __FUNCTION__, data_types[buf->data_type], offset, length); if (BRW_DUMP) brw_dump_data( idws->base.pci_id, buf->data_type, buf->bo->offset + offset, (char*)buf->bo->virtual + offset, length, buffer->sws->gen ); } static void i965_libdrm_bo_unmap(struct brw_winsys_buffer *buffer) { struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); if (BRW_DUMP) debug_printf("%s\n", __FUNCTION__); if (--buf->map_count > 0) return; if (buf->map_gtt) drm_intel_gem_bo_unmap_gtt(buf->bo); else drm_intel_bo_unmap(buf->bo); } void i965_libdrm_winsys_init_buffer_functions(struct i965_libdrm_winsys *idws) { idws->base.bo_alloc = i965_libdrm_bo_alloc; idws->base.bo_from_handle = i965_libdrm_bo_from_handle; idws->base.bo_get_handle = i965_libdrm_bo_get_handle; idws->base.bo_destroy = i965_libdrm_bo_destroy; idws->base.bo_emit_reloc = i965_libdrm_bo_emit_reloc; idws->base.bo_exec = i965_libdrm_bo_exec; idws->base.bo_subdata = i965_libdrm_bo_subdata; idws->base.bo_is_busy = i965_libdrm_bo_is_busy; idws->base.bo_references = i965_libdrm_bo_references; idws->base.check_aperture_space = i965_libdrm_check_aperture_space; idws->base.bo_map = i965_libdrm_bo_map; idws->base.bo_flush_range = i965_libdrm_bo_flush_range; idws->base.bo_unmap = i965_libdrm_bo_unmap; }