From da25b288eef7e69786b8aef03f9b01b68ffdff87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Thu, 7 Jul 2022 17:35:21 +0200 Subject: [PATCH] libports: add mesa/lima driver This commit introduces the Mesa3D lima driver for Mali 400 series GPUs. Issue #4559. --- .../libports/include/libdrm/ioctl_dispatch.h | 2 +- repos/libports/lib/mk/mesa.inc | 4 + repos/libports/lib/mk/spec/arm_v8/libdrm.mk | 3 +- repos/libports/lib/mk/spec/arm_v8/lima.mk | 64 ++ repos/libports/lib/mk/spec/arm_v8/mesa.mk | 9 +- .../lib/mk/spec/arm_v8/mesa_gpu-lima.mk | 19 + repos/libports/ports/mesa.hash | 2 +- repos/libports/ports/mesa.port | 16 +- repos/libports/recipes/src/libdrm/content.mk | 3 +- repos/libports/recipes/src/libdrm/used_apis | 1 + repos/libports/recipes/src/mesa/content.mk | 2 + .../libports/src/lib/libdrm/ioctl_dispatch.cc | 32 + repos/libports/src/lib/libdrm/ioctl_lima.cc | 864 ++++++++++++++++++ repos/libports/src/lib/mesa/files.list | 67 ++ repos/libports/src/lib/mesa/lima/drm_init.cc | 27 + .../src/lib/mesa/lima/platform_lima.c | 269 ++++++ repos/libports/src/lib/mesa/lima/target.mk | 3 + .../libports/src/lib/mesa/patches/lima.patch | 12 + .../src/lib/mesa/patches/sync_wait.patch | 20 + 19 files changed, 1408 insertions(+), 11 deletions(-) create mode 100644 repos/libports/lib/mk/spec/arm_v8/lima.mk create mode 100644 repos/libports/lib/mk/spec/arm_v8/mesa_gpu-lima.mk create mode 100644 repos/libports/src/lib/libdrm/ioctl_lima.cc create mode 100644 repos/libports/src/lib/mesa/lima/drm_init.cc create mode 100644 repos/libports/src/lib/mesa/lima/platform_lima.c create mode 100644 repos/libports/src/lib/mesa/lima/target.mk create mode 100644 repos/libports/src/lib/mesa/patches/lima.patch create mode 100644 repos/libports/src/lib/mesa/patches/sync_wait.patch diff --git a/repos/libports/include/libdrm/ioctl_dispatch.h b/repos/libports/include/libdrm/ioctl_dispatch.h index 182961b55d..df238795da 100644 --- a/repos/libports/include/libdrm/ioctl_dispatch.h +++ b/repos/libports/include/libdrm/ioctl_dispatch.h @@ -16,7 +16,7 @@ #define _INCLUDE__LIBDRM__IOCTL_DISPATCH_H_ namespace Libdrm { - enum Driver { INVALID, ETNAVIV }; + enum Driver { INVALID, ETNAVIV, LIMA }; }; /* namespace Libdrm */ void drm_init(Libdrm::Driver); diff --git a/repos/libports/lib/mk/mesa.inc b/repos/libports/lib/mk/mesa.inc index 86c4447a03..ba3271f4b8 100644 --- a/repos/libports/lib/mk/mesa.inc +++ b/repos/libports/lib/mk/mesa.inc @@ -232,6 +232,7 @@ SRC_C += compiler/glsl/glcpp/pp.c \ compiler/nir/nir_lower_drawpixels.c \ compiler/nir/nir_lower_flatshade.c \ compiler/nir/nir_lower_flrp.c \ + compiler/nir/nir_lower_fragcoord_wtrans.c \ compiler/nir/nir_lower_frexp.c \ compiler/nir/nir_lower_global_vars_to_local.c \ compiler/nir/nir_lower_goto_ifs.c \ @@ -253,6 +254,7 @@ SRC_C += compiler/glsl/glcpp/pp.c \ compiler/nir/nir_lower_patch_vertices.c \ compiler/nir/nir_lower_phis_to_scalar.c \ compiler/nir/nir_lower_pntc_ytransform.c \ + compiler/nir/nir_lower_point_size.c \ compiler/nir/nir_lower_point_size_mov.c \ compiler/nir/nir_lower_regs_to_ssa.c \ compiler/nir/nir_lower_returns.c \ @@ -268,6 +270,7 @@ SRC_C += compiler/glsl/glcpp/pp.c \ compiler/nir/nir_lower_variable_initializers.c \ compiler/nir/nir_lower_vars_to_ssa.c \ compiler/nir/nir_lower_vec_to_movs.c \ + compiler/nir/nir_lower_viewport_transform.c \ compiler/nir/nir_lower_wpos_ytransform.c \ compiler/nir/nir_metadata.c \ compiler/nir/nir_move_vec_src_uses_to_dest.c \ @@ -448,6 +451,7 @@ SRC_C += compiler/glsl/glcpp/pp.c \ gallium/auxiliary/util/u_sampler.c \ gallium/auxiliary/util/u_screen.c \ gallium/auxiliary/util/u_simple_shaders.c \ + gallium/auxiliary/util/u_split_draw.c \ gallium/auxiliary/util/u_surface.c \ gallium/auxiliary/util/u_tests.c \ gallium/auxiliary/util/u_texture.c \ diff --git a/repos/libports/lib/mk/spec/arm_v8/libdrm.mk b/repos/libports/lib/mk/spec/arm_v8/libdrm.mk index 38d22b67ed..36683650b4 100644 --- a/repos/libports/lib/mk/spec/arm_v8/libdrm.mk +++ b/repos/libports/lib/mk/spec/arm_v8/libdrm.mk @@ -3,5 +3,6 @@ include $(REP_DIR)/lib/mk/libdrm.inc LIBS += vfs_gpu include $(call select_from_repositories,lib/import/import-libdrm.mk) +include $(call select_from_repositories,lib/import/import-mesa_api.mk) -SRC_CC := ioctl_dispatch.cc ioctl_etnaviv.cc +SRC_CC := ioctl_dispatch.cc ioctl_etnaviv.cc ioctl_lima.cc diff --git a/repos/libports/lib/mk/spec/arm_v8/lima.mk b/repos/libports/lib/mk/spec/arm_v8/lima.mk new file mode 100644 index 0000000000..21493852b6 --- /dev/null +++ b/repos/libports/lib/mk/spec/arm_v8/lima.mk @@ -0,0 +1,64 @@ +LIBS = libc libdrm + +include $(REP_DIR)/lib/mk/mesa-common.inc + +INC_DIR += $(MESA_SRC_DIR)/src/compiler/nir \ + $(MESA_SRC_DIR)/src/gallium/auxiliary \ + $(MESA_SRC_DIR)/src/gallium/drivers \ + $(MESA_SRC_DIR)/src/gallium/drivers/lima \ + $(MESA_SRC_DIR)/src/panfrost/shared \ + $(MESA_SRC_DIR)/src/util \ + $(MESA_GEN_DIR)/src/compiler/nir \ + $(MESA_PORT_DIR)/include/drm-uapi + +REP_INC_DIR += include/drm-uapi + +SRC_C := \ + gallium/drivers/lima/lima_draw.c \ + gallium/drivers/lima/lima_job.c \ + gallium/drivers/lima/lima_context.c \ + gallium/drivers/lima/ir/pp/node_to_instr.c \ + gallium/drivers/lima/ir/pp/liveness.c \ + gallium/drivers/lima/ir/pp/codegen.c \ + gallium/drivers/lima/ir/pp/nir.c \ + gallium/drivers/lima/ir/pp/disasm.c \ + gallium/drivers/lima/ir/pp/regalloc.c \ + gallium/drivers/lima/ir/pp/node.c \ + gallium/drivers/lima/ir/pp/instr.c \ + gallium/drivers/lima/ir/pp/lower.c \ + gallium/drivers/lima/ir/pp/scheduler.c \ + gallium/drivers/lima/ir/gp/codegen.c \ + gallium/drivers/lima/ir/gp/nir.c \ + gallium/drivers/lima/ir/gp/disasm.c \ + gallium/drivers/lima/ir/gp/regalloc.c \ + gallium/drivers/lima/ir/gp/optimize.c \ + gallium/drivers/lima/ir/gp/node.c \ + gallium/drivers/lima/ir/gp/reduce_scheduler.c \ + gallium/drivers/lima/ir/gp/instr.c \ + gallium/drivers/lima/ir/gp/lower.c \ + gallium/drivers/lima/ir/gp/scheduler.c \ + gallium/drivers/lima/ir/lima_nir_split_load_input.c \ + gallium/drivers/lima/ir/lima_nir_duplicate_consts.c \ + gallium/drivers/lima/ir/lima_nir_duplicate_intrinsic.c \ + gallium/drivers/lima/ir/lima_nir_lower_uniform_to_scalar.c \ + gallium/drivers/lima/lima_bo.c \ + gallium/drivers/lima/lima_context.c \ + gallium/drivers/lima/lima_draw.c \ + gallium/drivers/lima/lima_fence.c \ + gallium/drivers/lima/lima_format.c \ + gallium/drivers/lima/lima_job.c \ + gallium/drivers/lima/lima_parser.c \ + gallium/drivers/lima/lima_program.c \ + gallium/drivers/lima/lima_query.c \ + gallium/drivers/lima/lima_resource.c \ + gallium/drivers/lima/lima_screen.c \ + gallium/drivers/lima/lima_state.c \ + gallium/drivers/lima/lima_texture.c \ + gallium/drivers/lima/lima_util.c \ + gallium/drivers/lima/lima_nir_algebraic.c \ + gallium/winsys/lima/drm/lima_drm_winsys.c \ + panfrost/shared/pan_minmax_cache.c \ + panfrost/shared/pan_tiling.c + +vpath %.c $(MESA_SRC_DIR)/src +vpath %.c $(MESA_SRC_DIR)/../../../generated/src diff --git a/repos/libports/lib/mk/spec/arm_v8/mesa.mk b/repos/libports/lib/mk/spec/arm_v8/mesa.mk index f8874ce1cf..ff57794caf 100644 --- a/repos/libports/lib/mk/spec/arm_v8/mesa.mk +++ b/repos/libports/lib/mk/spec/arm_v8/mesa.mk @@ -1,10 +1,13 @@ SHARED_LIB := yes LIBS += libdrm -LIBS += etnaviv +CC_OPT += -DHAVE_UINT128 -CC_OPT += -DGALLIUM_ETNAVIV \ - -DHAVE_UINT128 +LIBS += etnaviv +CC_OPT += -DGALLIUM_ETNAVIV + +LIBS += lima +CC_OPT += -DGALLIUM_LIMA include $(REP_DIR)/lib/mk/mesa.inc diff --git a/repos/libports/lib/mk/spec/arm_v8/mesa_gpu-lima.mk b/repos/libports/lib/mk/spec/arm_v8/mesa_gpu-lima.mk new file mode 100644 index 0000000000..d88c593519 --- /dev/null +++ b/repos/libports/lib/mk/spec/arm_v8/mesa_gpu-lima.mk @@ -0,0 +1,19 @@ +SHARED_LIB := yes +LIBS := libc egl + +include $(REP_DIR)/lib/mk/mesa-common.inc + +SRC_CC := drm_init.cc +SRC_C := platform_lima.c + +CC_OPT += -DHAVE_GENODE_PLATFORM + +INC_DIR += $(MESA_SRC_DIR)/src/egl/drivers/dri2 \ + $(MESA_SRC_DIR)/src/egl/main \ + $(MESA_SRC_DIR)/src/mapi \ + $(MESA_SRC_DIR)/src/mesa + +vpath %.c $(LIB_DIR)/lima +vpath %.cc $(LIB_DIR)/lima + +CC_CXX_WARN_STRICT := diff --git a/repos/libports/ports/mesa.hash b/repos/libports/ports/mesa.hash index 2b978bef9b..10cd30a7c9 100644 --- a/repos/libports/ports/mesa.hash +++ b/repos/libports/ports/mesa.hash @@ -1 +1 @@ -2a8726a52ca7b243fcf40d07da28a52aba4c767f +a195203391df18dabe0e9c247301d9f3df1c8192 diff --git a/repos/libports/ports/mesa.port b/repos/libports/ports/mesa.port index 63de2f8adb..ffb87f3a4d 100644 --- a/repos/libports/ports/mesa.port +++ b/repos/libports/ports/mesa.port @@ -23,15 +23,17 @@ PATCHES := src/lib/mesa/patches/bitset_redefined.patch \ src/lib/mesa/patches/lseek.patch \ src/lib/mesa/patches/mesa.patch \ src/lib/mesa/patches/os_mmap.patch \ - src/lib/mesa/patches/softpipe_cache.patch + src/lib/mesa/patches/softpipe_cache.patch \ + src/lib/mesa/patches/lima.patch \ + src/lib/mesa/patches/sync_wait.patch PATCH_OPT := -p1 # # Generated Mesa sources # -URL(generated) = https://github.com/ssumpf/mesa_generated.git -REV(generated) = 396d4b08cbcff941126640e6d3e3d2a5f807d527 +URL(generated) = https://github.com/cnuke/mesa_generated.git +REV(generated) = c3954da3f66d6cb961421f03c09d589faade1784 DIR(generated) = generated # @@ -110,7 +112,8 @@ generated_files = $(GEN_TARGET)/src/compiler/glsl/float64_glsl.h \ $(GEN_TARGET)/src/intel/genxml/genX_bits.h \ $(GEN_TARGET)/src/intel/genxml/genX_xml.h \ $(GEN_TARGET)/src/intel/isl/isl_format_layout.c \ - $(GEN_TARGET)/src/intel/perf/gen_perf_metrics.h + $(GEN_TARGET)/src/intel/perf/gen_perf_metrics.h \ + $(GEN_TARGET)/src/gallium/drivers/lima/lima_nir_algebraic.c # # Print message and create directory @@ -345,6 +348,11 @@ $(GEN_TARGET)/src/intel/perf/gen_perf_metrics.h: $(SRC)/src/intel/perf/oa-sklgt4.xml \ $(SRC)/src/intel/perf/oa-tgl.xml +$(GEN_TARGET)/src/gallium/drivers/lima/lima_nir_algebraic.c: + $(MSG_DIR) + $(VERBOSE)$(PYTHON) $(SRC)/src/gallium/drivers/lima/ir/lima_nir_algebraic.py \ + -p $(SRC)/src/compiler/nir/ > $@ + CMD(glcpp-lex.c) = glcpp-lex.l CMD(glsl_lexer.cpp) = glsl_lexer.ll CMD(lex.yy.c) = program_lexer.l diff --git a/repos/libports/recipes/src/libdrm/content.mk b/repos/libports/recipes/src/libdrm/content.mk index 7872ba245b..58fed75624 100644 --- a/repos/libports/recipes/src/libdrm/content.mk +++ b/repos/libports/recipes/src/libdrm/content.mk @@ -8,7 +8,8 @@ MIRROR_FROM_REP_DIR := lib/mk/libdrm.mk \ src/lib/libdrm/ioctl_dummy.cc \ src/lib/libdrm/ioctl_iris.cc \ src/lib/libdrm/ioctl_etnaviv.cc \ - src/lib/libdrm/ioctl_dispatch.cc + src/lib/libdrm/ioctl_dispatch.cc \ + src/lib/libdrm/ioctl_lima.cc content: $(MIRROR_FROM_REP_DIR) src/lib/libdrm/target.mk diff --git a/repos/libports/recipes/src/libdrm/used_apis b/repos/libports/recipes/src/libdrm/used_apis index d33079a30a..5f9364f5c4 100644 --- a/repos/libports/recipes/src/libdrm/used_apis +++ b/repos/libports/recipes/src/libdrm/used_apis @@ -2,3 +2,4 @@ base gpu_session libc vfs_gpu +mesa diff --git a/repos/libports/recipes/src/mesa/content.mk b/repos/libports/recipes/src/mesa/content.mk index 8c55501d84..21fc2bfd8a 100644 --- a/repos/libports/recipes/src/mesa/content.mk +++ b/repos/libports/recipes/src/mesa/content.mk @@ -12,8 +12,10 @@ MIRROR_FROM_REP_DIR := \ lib/mk/mesa-common.inc \ lib/mk/softpipe.mk \ lib/mk/spec/arm_v8/etnaviv.mk \ + lib/mk/spec/arm_v8/lima.mk \ lib/mk/spec/arm_v8/mesa.mk \ lib/mk/spec/arm_v8/mesa_gpu-etnaviv.mk \ + lib/mk/spec/arm_v8/mesa_gpu-lima.mk \ lib/mk/spec/x86/mesa_gpu-iris.mk \ lib/mk/spec/x86/iris.mk \ lib/mk/spec/x86/iris_gen110.mk \ diff --git a/repos/libports/src/lib/libdrm/ioctl_dispatch.cc b/repos/libports/src/lib/libdrm/ioctl_dispatch.cc index 0f8fee1b41..6932529e39 100644 --- a/repos/libports/src/lib/libdrm/ioctl_dispatch.cc +++ b/repos/libports/src/lib/libdrm/ioctl_dispatch.cc @@ -33,6 +33,14 @@ extern int etnaviv_drm_ioctl(unsigned long, void *); extern void *etnaviv_drm_mmap(off_t, size_t); extern int etnaviv_drm_munmap(void *); +/* lima driver */ + +extern void lima_drm_init(); +extern int lima_drm_ioctl(unsigned long, void *); +extern void *lima_drm_mmap(off_t, size_t); +extern int lima_drm_munmap(void *); +extern int lima_drm_poll(int); + static Libdrm::Driver drm_backend_type = Libdrm::Driver::INVALID; @@ -47,6 +55,10 @@ void drm_init(Libdrm::Driver driver) etnaviv_drm_init(); drm_backend_type = Libdrm::Driver::ETNAVIV; break; + case Libdrm::Driver::LIMA: + lima_drm_init(); + drm_backend_type = Libdrm::Driver::LIMA; + break; default: Genode::error(__func__, ": unknown back end, abort"); abort(); @@ -61,6 +73,7 @@ extern "C" int genode_ioctl(int /* fd */, unsigned long request, void *arg) { switch (drm_backend_type) { case Libdrm::Driver::ETNAVIV: return etnaviv_drm_ioctl(request, arg); + case Libdrm::Driver::LIMA: return lima_drm_ioctl(request, arg); default: return -1; } } @@ -79,6 +92,7 @@ extern "C" void *drm_mmap(void *addr, size_t length, int prot, int flags, switch (drm_backend_type) { case Libdrm::Driver::ETNAVIV: return etnaviv_drm_mmap(offset, length); + case Libdrm::Driver::LIMA: return lima_drm_mmap(offset, length); default: return NULL; } } @@ -93,6 +107,24 @@ extern "C" int drm_munmap(void *addr, size_t length) switch (drm_backend_type) { case Libdrm::Driver::ETNAVIV: return etnaviv_drm_munmap(addr); + case Libdrm::Driver::LIMA: return lima_drm_munmap(addr); + default: return -1; + } +} + + +extern "C" int drm_poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + (void)timeout; + + if (nfds > 1) { + Genode::error(__func__, ": cannot handle more the 1 pollfd"); + return -1; + } + + switch (drm_backend_type) { + case Libdrm::Driver::ETNAVIV: return -1; + case Libdrm::Driver::LIMA: return lima_drm_poll(fds[0].fd); default: return -1; } } diff --git a/repos/libports/src/lib/libdrm/ioctl_lima.cc b/repos/libports/src/lib/libdrm/ioctl_lima.cc new file mode 100644 index 0000000000..358f0a0b06 --- /dev/null +++ b/repos/libports/src/lib/libdrm/ioctl_lima.cc @@ -0,0 +1,864 @@ +/* + * \brief DRM ioctl backend + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2017-05-10 + */ + +/* + * Copyright (C) 2017-2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include + +#include + +extern "C" { +#include +#include +#include +#include +#include +#include + +#include +#include +#include +} + + +enum { verbose_ioctl = false }; + + +/** + * Get DRM command number + */ +static unsigned long constexpr command_number(unsigned long request) +{ + return request & 0xffu; +} + + +/** + * Get device specific command number + */ +static unsigned long device_number(unsigned long request) +{ + return command_number(request) - DRM_COMMAND_BASE; +} + + +/** + * Check if request is device command + */ +static bool device_ioctl(unsigned long request) +{ + long const cmd = command_number(request); + return cmd >= DRM_COMMAND_BASE && cmd < DRM_COMMAND_END; +} + + +/** + * Return name of DRM command + */ +const char *command_name(unsigned long request) +{ + if (IOCGROUP(request) != DRM_IOCTL_BASE) + return ""; + + if (!device_ioctl(request)) { + switch (command_number(request)) { + case command_number(DRM_IOCTL_GEM_CLOSE): return "DRM_IOCTL_GEM_CLOSE"; + case command_number(DRM_IOCTL_GEM_FLINK): return "DRM_IOCTL_GEM_FLINK"; + case command_number(DRM_IOCTL_GEM_OPEN): return "DRM_IOCTL_GEM_OPEN"; + case command_number(DRM_IOCTL_GET_CAP): return "DRM_IOCTL_GET_CAP"; + case command_number(DRM_IOCTL_GET_UNIQUE): return "DRM_IOCTL_GET_UNIQUE"; + case command_number(DRM_IOCTL_PRIME_FD_TO_HANDLE): return "DRM_IOCTL_PRIME_FD_TO_HANDLE"; + case command_number(DRM_IOCTL_PRIME_HANDLE_TO_FD): return "DRM_IOCTL_PRIME_HANDLE_TO_FD"; + case command_number(DRM_IOCTL_SYNCOBJ_CREATE): return "DRM_IOCTL_SYNCOBJ_CREATE"; + case command_number(DRM_IOCTL_SYNCOBJ_DESTROY): return "DRM_IOCTL_SYNCOBJ_DESTROY"; + case command_number(DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD): return "DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD"; + case command_number(DRM_IOCTL_VERSION): return "DRM_IOCTL_VERSION"; + default: return ""; + } + } + + switch (device_number(request)) { + case DRM_LIMA_CTX_CREATE: return "DRM_LIMA_CTX_CREATE"; + case DRM_LIMA_CTX_FREE: return "DRM_LIMA_CTX_FREE"; + case DRM_LIMA_GET_PARAM: return "DRM_LIMA_GET_PARAM"; + case DRM_LIMA_GEM_CREATE: return "DRM_LIMA_GEM_CREATE"; + case DRM_LIMA_GEM_INFO: return "DRM_LIMA_GEM_INFO"; + case DRM_LIMA_GEM_SUBMIT: return "DRM_LIMA_GEM_SUBMIT"; + case DRM_LIMA_GEM_WAIT: return "DRM_LIMA_GEM_WAIT"; + default: return ""; + } +} + + +namespace Lima { + + size_t get_payload_size(drm_lima_gem_submit const &submit); + + // XXX better implement as 'size_t for_each_object(T const *t, unsigned len, FN const &fn, char *dst)' + template void for_each_object(T const *t, unsigned len, FN const &fn) + { + for (unsigned i = 0; i < len; i++) { + T const *obj = &t[i]; + fn(obj); + } + } + + void serialize(drm_lima_gem_submit *submit, char *content); + + size_t get_payload_size(drm_version const &version); + +} /* anonymous namespace */ + + +size_t Lima::get_payload_size(drm_lima_gem_submit const &submit) +{ + size_t size = 0; + + size += sizeof (drm_lima_gem_submit_bo) * submit.nr_bos; + size += submit.frame_size; + + return size; +} + + +void Lima::serialize(drm_lima_gem_submit *submit, char *content) +{ + size_t offset = 0; + + /* leave place for object itself first */ + offset += sizeof (*submit); + + /* next are the buffer-objects */ + if (submit->nr_bos) { + size_t const new_start = offset; + + auto copy_bos = [&] (drm_lima_gem_submit_bo const *bo) { + char * const dst = content + offset; + Genode::memcpy(dst, bo, sizeof (*bo)); + offset += sizeof (*bo); + }; + for_each_object((drm_lima_gem_submit_bo*)submit->bos, + submit->nr_bos, copy_bos); + submit->bos = reinterpret_cast<__u64>(new_start); + } + + /* next is the frame */ + { + size_t const new_start = offset; + + char * const dst = content + offset; + Genode::memcpy(dst, reinterpret_cast(submit->frame), submit->frame_size); + offset += submit->frame_size; + submit->frame = reinterpret_cast<__u64>(new_start); + } + + /* copy submit object last but into the front */ + Genode::memcpy(content, submit, sizeof (*submit)); +} + + +size_t Lima::get_payload_size(drm_version const &version) +{ + size_t size = 0; + size += version.name_len; + size += version.date_len; + size += version.desc_len; + return size; +} + + +namespace Lima { + using namespace Genode; + using namespace Gpu; + + struct Call; +} /* namespace Gpu */ + + +struct Gpu::Buffer +{ + Gpu::Connection &_gpu; + + Genode::Id_space::Element const _elem; + + Genode::Dataspace_capability const cap; + size_t const size; + + Genode::Constructible _attached_buffer { }; + + Buffer(Gpu::Connection &gpu, + size_t size, + Genode::Id_space &space) + : + _gpu { gpu }, + _elem { *this, space }, + cap { _gpu.alloc_buffer(_elem.id(), size) }, + size { size } + { } + + virtual ~Buffer() + { + _gpu.free_buffer(_elem.id()); + } + + bool mmap(Genode::Env &env) + { + if (!_attached_buffer.constructed()) { + _attached_buffer.construct(env.rm(), cap); + } + + return _attached_buffer.constructed(); + } + + Genode::addr_t mmap_addr() + { + return reinterpret_cast(_attached_buffer->local_addr()); + } + + Gpu::Buffer_id id() const + { + return _elem.id(); + } +}; + + +class Lima::Call +{ + private: + + /* + * Noncopyable + */ + Call(Call const &) = delete; + Call &operator=(Call const &) = delete; + + Genode::Env &_env { *vfs_gpu_env() }; + Genode::Heap _heap { _env.ram(), _env.rm() }; + + /***************** + ** Gpu session ** + *****************/ + + struct Gpu_context + { + int const fd; + unsigned long const _gpu_id; + + Gpu::Connection &_gpu { *vfs_gpu_connection(_gpu_id) }; + + using Id_space = Genode::Id_space; + Id_space::Element const _elem; + + Gpu_context(int fd, unsigned long gpu, + Genode::Id_space &space) + : fd { fd }, _gpu_id { gpu }, _elem { *this, space } { } + + virtual ~Gpu_context() + { + ::close(fd); + } + + unsigned long id() const + { + return _elem.id().value; + } + + Gpu::Connection& gpu() + { + return _gpu; + } + }; + + using Gpu_context_space = Genode::Id_space; + Gpu_context_space _gpu_context_space { }; + + Gpu_context &_create_ctx() + { + int const fd = ::open("/dev/gpu", 0); + if (fd < 0) { + Genode::error("Failed to open '/dev/gpu': ", + "try configure '' in 'dev' directory of VFS'"); + throw Gpu::Session::Invalid_state(); + } + + struct ::stat buf; + if (::fstat(fd, &buf) < 0) { + Genode::error("Could not stat '/dev/gpu'"); + ::close(fd); + throw Gpu::Session::Invalid_state(); + } + Gpu_context * context = + new (_heap) Gpu_context(fd, buf.st_ino, _gpu_context_space); + + return *context; + } + + struct Syncobj + { + /* + * Noncopyable + */ + Syncobj(Syncobj const &) = delete; + Syncobj &operator=(Syncobj const &) = delete; + + + Gpu_context *_gc { nullptr }; + Gpu::Sequence_number _seqno { 0 }; + + using Id_space = Genode::Id_space; + Id_space::Element const _elem; + + Syncobj(Id_space &space) + : _elem { *this, space } { } + + unsigned long id() const + { + return _elem.id().value; + } + + void adopt(Gpu_context &gc, Gpu::Sequence_number seqno) + { + _gc = &gc; + _seqno = seqno; + } + + Gpu_context &gpu_context() + { + if (!_gc) { + struct Invalid_gpu_context { }; + throw Invalid_gpu_context(); + } + + return *_gc; + } + + Gpu::Sequence_number seqno() const + { + return _seqno; + } + }; + Genode::Id_space _syncobj_space { }; + + struct Gpu_session + { + int const fd; + unsigned long const id; + + Gpu_session(int fd, unsigned long id) + : fd { fd }, id { id } { } + + virtual ~Gpu_session() + { + ::close(fd); + } + + Gpu::Connection &gpu() + { + return *vfs_gpu_connection(id); + } + }; + + Gpu_session _open_gpu() + { + int const fd = ::open("/dev/gpu", 0); + if (fd < 0) { + Genode::error("Failed to open '/dev/gpu': ", + "try configure '' in 'dev' directory of VFS'"); + throw Gpu::Session::Invalid_state(); + } + + struct ::stat buf; + if (::fstat(fd, &buf) < 0) { + Genode::error("Could not stat '/dev/gpu'"); + ::close(fd); + throw Gpu::Session::Invalid_state(); + } + + return Gpu_session { fd, buf.st_ino }; + } + + Gpu_session _gpu_session { _open_gpu() }; + + Gpu::Connection &_gpu { _gpu_session.gpu() }; + Gpu::Info_lima const &_gpu_info { + *_gpu.attached_info() }; + + Id_space _buffer_space { }; + + /* + * Play it safe, glmark2 apparently submits araound 110 KiB at + * some point. + */ + enum { EXEC_BUFFER_SIZE = 256u << 10 }; + Constructible _exec_buffer { }; + + void _wait_for_mapping(uint32_t handle, unsigned op) + { + Buffer_id const id { .value = handle }; + do { + if (_gpu.set_tiling(id, op)) + break; + + char buf; + (void)::read(_gpu_session.fd, &buf, sizeof(buf)); + } while (true); + } + + void _wait_for_syncobj(unsigned int handle) + { + Syncobj::Id_space::Id syncobj_id { .value = handle }; + + try { + auto wait = [&] (Syncobj &sync_obj) { + + Gpu_context &gc = sync_obj.gpu_context(); + do { + if (gc.gpu().complete(sync_obj.seqno())) + break; + + char buf; + (void)::read(gc.fd, &buf, sizeof(buf)); + } while (true); + }; + _syncobj_space.apply(syncobj_id, wait); + } catch (Genode::Id_space::Unknown_id) { } + } + + template + bool _apply_handle(uint32_t handle, FN const &fn) + { + Buffer_id const id { .value = handle }; + + bool found = false; + _buffer_space.apply(id, [&] (Buffer &b) { + fn(b); + found = true; + }); + + return found; + } + + Dataspace_capability _lookup_cap_from_handle(uint32_t handle) + { + Dataspace_capability cap { }; + auto lookup_cap = [&] (Buffer const &b) { + cap = b.cap; + }; + (void)_apply_handle(handle, lookup_cap); + return cap; + } + + /****************************** + ** Device DRM I/O controls ** + ******************************/ + + int _drm_lima_gem_info(drm_lima_gem_info &arg) + { + int result = -1; + (void)_apply_handle(arg.handle, [&] (Buffer &b) { + if (!b.mmap(_env)) + return; + arg.offset = reinterpret_cast<::uint64_t>(b.mmap_addr()); + + Gpu::addr_t const va = _gpu.query_buffer_ppgtt(b.id()); + if (va == (Gpu::addr_t)-1) + return; + arg.va = (uint32_t)va; + + result = 0; + }); + + return result; + } + + template + void _alloc_buffer(::uint64_t const size, FUNC const &fn) + { + size_t donate = size; + Buffer *buffer = nullptr; + + retry( + [&] () { + retry( + [&] () { + buffer = + new (&_heap) Buffer(_gpu, size, + _buffer_space); + }, + [&] () { + _gpu.upgrade_caps(2); + }); + }, + [&] () { + _gpu.upgrade_ram(donate); + }); + + if (buffer) + fn(*buffer); + } + + int _drm_lima_gem_create(drm_lima_gem_create &arg) + { + ::uint64_t const size = arg.size; + + try { + _alloc_buffer(size, [&](Buffer const &b) { + arg.handle = b.id().value; + }); + return 0; + } catch (...) { + return -1; + } + } + + int _drm_lima_gem_submit(drm_lima_gem_submit &arg) + { + Gpu_context::Id_space::Id ctx_id { .value = arg.ctx }; + + Syncobj::Id_space::Id syncobj_id { .value = arg.out_sync }; + + bool result = false; + _syncobj_space.apply(syncobj_id, [&] (Syncobj &sync_obj) { + + _gpu_context_space.apply(ctx_id, [&] (Gpu_context &gc) { + + size_t const payload_size = Lima::get_payload_size(arg); + if (payload_size > EXEC_BUFFER_SIZE) { + Genode::error(__func__, ": exec buffer too small (", + (unsigned)EXEC_BUFFER_SIZE, ") needed ", payload_size); + return; + } + + /* + * Copy each array flat to the exec buffer and adjust the + * addresses in the submit object. + */ + char *local_exec_buffer = (char*)_exec_buffer->mmap_addr(); + Genode::memset(local_exec_buffer, 0, EXEC_BUFFER_SIZE); + Lima::serialize(&arg, local_exec_buffer); + + try { + Gpu::Connection &gpu = gc.gpu(); + + Gpu::Sequence_number const seqno = + gpu.exec_buffer(_exec_buffer->id(), EXEC_BUFFER_SIZE); + + sync_obj.adopt(gc, seqno); + + result = true; + } catch (Gpu::Session::Invalid_state) { } + }); + }); + + return result ? 0 : -1; + } + + int _drm_lima_gem_wait(drm_lima_gem_wait &arg) + { + /* + * For the moment we do not handle timeouts + */ + (void)arg.timeout_ns; + _wait_for_mapping(arg.handle, arg.op); + return 0; + } + + int _drm_lima_get_param(drm_lima_get_param &arg) + { + if (arg.param > Gpu::Info_lima::MAX_LIMA_PARAMS) { + errno = EINVAL; + return -1; + } + + arg.value = _gpu_info.param[arg.param]; + return 0; + } + + int _drm_lima_ctx_create(drm_lima_ctx_create &arg) + { + try { + Gpu_context &ctx = _create_ctx(); + + arg.id = ctx.id(); + return 0; + } catch (... /* intentional catch-all ... */) { + /* ... as the lima GPU driver will not throw */ + } + return -1; + } + + int _drm_lima_ctx_free(drm_lima_ctx_free &arg) + { + Gpu_context::Id_space::Id id { .value = arg.id }; + + bool result = false; + auto free_ctx = [&] (Gpu_context &ctx) { + ::close(ctx.fd); + Genode::destroy(_heap, &ctx); + result = true; + }; + _gpu_context_space.apply(id, free_ctx); + + return result ? 0 : -1; + } + + int _device_ioctl(unsigned cmd, void *arg) + { + if (!arg) { + errno = EINVAL; + return -1; + } + + switch (cmd) { + case DRM_LIMA_CTX_CREATE: + return _drm_lima_ctx_create(*reinterpret_cast(arg)); + case DRM_LIMA_CTX_FREE: + return _drm_lima_ctx_free(*reinterpret_cast(arg)); + case DRM_LIMA_GEM_INFO: + return _drm_lima_gem_info(*reinterpret_cast(arg)); + case DRM_LIMA_GEM_CREATE: + return _drm_lima_gem_create(*reinterpret_cast(arg)); + case DRM_LIMA_GEM_SUBMIT: + return _drm_lima_gem_submit(*reinterpret_cast(arg)); + case DRM_LIMA_GEM_WAIT: + return _drm_lima_gem_wait(*reinterpret_cast(arg)); + case DRM_LIMA_GET_PARAM: + return _drm_lima_get_param(*reinterpret_cast(arg)); + default: break; + } + + return 0; + } + + /******************************* + ** Generic DRM I/O controls ** + *******************************/ + + int _drm_gem_close(drm_gem_close const &gem_close) + { + return _apply_handle(gem_close.handle, + [&] (Gpu::Buffer &b) { + destroy(_heap, &b); + }) ? 0 : -1; + } + + int _drm_version(drm_version &version) + { + version.version_major = 1; + version.version_minor = 1; + version.version_patchlevel = 0; + + /** + * Libdrm probes the length by calling version twice + * and the second time strings are allocated. + */ + + version.name_len = 1; + if (version.name) + version.name[0] = '\0'; + version.date_len = 1; + if (version.date) + version.date[0] = '\0'; + version.desc_len = 1; + if (version.desc) + version.desc[0] = '\0'; + + return 0; + } + + int _drm_syncobj_create(drm_syncobj_create &arg) + { + try { + Syncobj *obj = new (_heap) Syncobj(_syncobj_space); + arg.handle = (uint32_t)obj->id(); + return 0; + } catch (... /* XXX which exceptions can occur? */) { } + return -1; + } + + int _drm_syncobj_destroy(drm_syncobj_destroy &arg) + { + Syncobj::Id_space::Id id { .value = arg.handle }; + + bool result = false; + _syncobj_space.apply(id, [&] (Syncobj &obj) { + Genode::destroy(_heap, &obj); + result = true; + }); + return result ? 0 : -1; + } + + int _drm_syncobj_handle_to_fd(drm_syncobj_handle &arg) + { + arg.fd = arg.handle + SYNC_FD; + return 0; + } + + int _generic_ioctl(unsigned cmd, void *arg) + { + if (!arg) { + errno = EINVAL; + return -1; + } + + switch (cmd) { + case command_number(DRM_IOCTL_GEM_CLOSE): + return _drm_gem_close(*reinterpret_cast(arg)); + case command_number(DRM_IOCTL_VERSION): + return _drm_version(*reinterpret_cast(arg)); + case command_number(DRM_IOCTL_SYNCOBJ_CREATE): + return _drm_syncobj_create(*reinterpret_cast(arg)); + case command_number(DRM_IOCTL_SYNCOBJ_DESTROY): + return _drm_syncobj_destroy(*reinterpret_cast(arg)); + case command_number(DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD): + return _drm_syncobj_handle_to_fd(*reinterpret_cast(arg)); + default: + error("unhandled generic DRM ioctl: ", Genode::Hex(cmd)); + break; + } + + return -1; + } + + + public: + + static constexpr int const SYNC_FD { 384 }; + + Call() + { + try { + _exec_buffer.construct(_gpu, + (size_t)EXEC_BUFFER_SIZE, + _buffer_space); + } catch (...) { + throw Gpu::Session::Invalid_state(); + } + if (!_exec_buffer->mmap(_env)) + throw Gpu::Session::Invalid_state(); + } + + ~Call() + { + while (_gpu_context_space.apply_any([&] (Gpu_context &ctx) { + Genode::destroy(_heap, &ctx); })) { ; } + + while (_syncobj_space.apply_any([&] (Syncobj &obj) { + Genode::destroy(_heap, &obj); })) { ; } + } + + int ioctl(unsigned long request, void *arg) + { + bool const device_request = device_ioctl(request); + return device_request ? _device_ioctl(device_number(request), arg) + : _generic_ioctl(command_number(request), arg); + } + + void *mmap(unsigned long offset, unsigned long /* size */) + { + /* + * Buffer should have been mapped during GEM INFO call. + */ + return (void*)offset; + } + + void munmap(void *addr) + { + /* + * We rely on GEM CLOSE to destroy the buffer and thereby + * to remove the local mapping. AFAICT the 'munmap' is indeed + * (always) followed by the CLOSE I/O control. + */ + (void)addr; + } + + void wait_for_syncobj(unsigned int handle) + { + _wait_for_syncobj(handle); + } +}; + + +static Genode::Constructible _drm; + + +void lima_drm_init() +{ + /* make sure VFS is initialized */ + struct ::stat buf; + if (stat("/dev/gpu", &buf) < 0) { + Genode::error("'/dev/gpu' not accessible: ", + "try configure '' in 'dev' directory of VFS'"); + return; + } + + _drm.construct(); +} + + +static void dump_ioctl(unsigned long request) +{ + using namespace Genode; + + log("ioctl(request=", Hex(request), + (request & 0xe0000000u) == IOC_OUT ? " out" : + (request & 0xe0000000u) == IOC_IN ? " in" : + (request & 0xe0000000u) == IOC_INOUT ? " inout" : " void", + " len=", IOCPARM_LEN(request), + " cmd=", command_name(request), " (", Hex(command_number(request)), "))"); +} + + +int lima_drm_ioctl(unsigned long request, void *arg) +{ + if (verbose_ioctl) + dump_ioctl(request); + + try { + int ret = _drm->ioctl(request, arg); + + if (verbose_ioctl) + Genode::log("returned ", ret); + + return ret; + } catch (...) { } + + return -1; +} + + +void *lima_drm_mmap(off_t offset, size_t length) +{ + return _drm->mmap(offset, length); +} + + +int lima_drm_munmap(void *addr) +{ + _drm->munmap(addr); + return 0; +} + + +int lima_drm_poll(int fd) +{ + int const handle = fd - Lima::Call::SYNC_FD; + _drm->wait_for_syncobj((unsigned)handle); + return 0; +} diff --git a/repos/libports/src/lib/mesa/files.list b/repos/libports/src/lib/mesa/files.list index 2139e3ea97..153d765346 100644 --- a/repos/libports/src/lib/mesa/files.list +++ b/repos/libports/src/lib/mesa/files.list @@ -285,6 +285,7 @@ mesa-21.0.0/src/compiler/nir/nir_lower_double_ops.c mesa-21.0.0/src/compiler/nir/nir_lower_drawpixels.c mesa-21.0.0/src/compiler/nir/nir_lower_flatshade.c mesa-21.0.0/src/compiler/nir/nir_lower_flrp.c +mesa-21.0.0/src/compiler/nir/nir_lower_fragcoord_wtrans.c mesa-21.0.0/src/compiler/nir/nir_lower_frexp.c mesa-21.0.0/src/compiler/nir/nir_lower_global_vars_to_local.c mesa-21.0.0/src/compiler/nir/nir_lower_goto_ifs.c @@ -305,6 +306,7 @@ mesa-21.0.0/src/compiler/nir/nir_lower_passthrough_edgeflags.c mesa-21.0.0/src/compiler/nir/nir_lower_patch_vertices.c mesa-21.0.0/src/compiler/nir/nir_lower_phis_to_scalar.c mesa-21.0.0/src/compiler/nir/nir_lower_pntc_ytransform.c +mesa-21.0.0/src/compiler/nir/nir_lower_point_size.c mesa-21.0.0/src/compiler/nir/nir_lower_point_size_mov.c mesa-21.0.0/src/compiler/nir/nir_lower_regs_to_ssa.c mesa-21.0.0/src/compiler/nir/nir_lower_returns.c @@ -320,6 +322,7 @@ mesa-21.0.0/src/compiler/nir/nir_lower_var_copies.c mesa-21.0.0/src/compiler/nir/nir_lower_variable_initializers.c mesa-21.0.0/src/compiler/nir/nir_lower_vars_to_ssa.c mesa-21.0.0/src/compiler/nir/nir_lower_vec_to_movs.c +mesa-21.0.0/src/compiler/nir/nir_lower_viewport_transform.c mesa-21.0.0/src/compiler/nir/nir_lower_wpos_ytransform.c mesa-21.0.0/src/compiler/nir/nir_metadata.c mesa-21.0.0/src/compiler/nir/nir_move_vec_src_uses_to_dest.c @@ -733,6 +736,7 @@ mesa-21.0.0/src/gallium/auxiliary/util/u_screen.c mesa-21.0.0/src/gallium/auxiliary/util/u_screen.h mesa-21.0.0/src/gallium/auxiliary/util/u_simple_shaders.c mesa-21.0.0/src/gallium/auxiliary/util/u_simple_shaders.h +mesa-21.0.0/src/gallium/auxiliary/util/u_split_draw.c mesa-21.0.0/src/gallium/auxiliary/util/u_split_draw.h mesa-21.0.0/src/gallium/auxiliary/util/u_split_prim.h mesa-21.0.0/src/gallium/auxiliary/util/u_sse.h @@ -841,6 +845,63 @@ mesa-21.0.0/src/gallium/drivers/etnaviv/hw/state_3d.xml.h mesa-21.0.0/src/gallium/drivers/etnaviv/hw/state_blt.xml.h mesa-21.0.0/src/gallium/drivers/etnaviv/hw/state.xml.h mesa-21.0.0/src/gallium/drivers/etnaviv/hw/texdesc_3d.xml.h + +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/codegen.c +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/codegen.h +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/disasm.c +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/gpir.h +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/instr.c +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/lower.c +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/nir.c +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/node.c +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/optimize.c +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/reduce_scheduler.c +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/regalloc.c +mesa-21.0.0/src/gallium/drivers/lima/ir/gp/scheduler.c +mesa-21.0.0/src/gallium/drivers/lima/ir/lima_ir.h +mesa-21.0.0/src/gallium/drivers/lima/ir/lima_nir_algebraic.py +mesa-21.0.0/src/gallium/drivers/lima/ir/lima_nir_duplicate_consts.c +mesa-21.0.0/src/gallium/drivers/lima/ir/lima_nir_duplicate_intrinsic.c +mesa-21.0.0/src/gallium/drivers/lima/ir/lima_nir_lower_uniform_to_scalar.c +mesa-21.0.0/src/gallium/drivers/lima/ir/lima_nir_split_load_input.c +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/codegen.c +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/codegen.h +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/disasm.c +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/instr.c +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/liveness.c +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/lower.c +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/nir.c +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/node.c +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/node_to_instr.c +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/ppir.h +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/regalloc.c +mesa-21.0.0/src/gallium/drivers/lima/ir/pp/scheduler.c +mesa-21.0.0/src/gallium/drivers/lima/lima_bo.c +mesa-21.0.0/src/gallium/drivers/lima/lima_bo.h +mesa-21.0.0/src/gallium/drivers/lima/lima_context.c +mesa-21.0.0/src/gallium/drivers/lima/lima_context.h +mesa-21.0.0/src/gallium/drivers/lima/lima_draw.c +mesa-21.0.0/src/gallium/drivers/lima/lima_fence.c +mesa-21.0.0/src/gallium/drivers/lima/lima_fence.h +mesa-21.0.0/src/gallium/drivers/lima/lima_format.c +mesa-21.0.0/src/gallium/drivers/lima/lima_format.h +mesa-21.0.0/src/gallium/drivers/lima/lima_gpu.h +mesa-21.0.0/src/gallium/drivers/lima/lima_job.c +mesa-21.0.0/src/gallium/drivers/lima/lima_job.h +mesa-21.0.0/src/gallium/drivers/lima/lima_parser.c +mesa-21.0.0/src/gallium/drivers/lima/lima_parser.h +mesa-21.0.0/src/gallium/drivers/lima/lima_program.c +mesa-21.0.0/src/gallium/drivers/lima/lima_program.h +mesa-21.0.0/src/gallium/drivers/lima/lima_query.c +mesa-21.0.0/src/gallium/drivers/lima/lima_resource.c +mesa-21.0.0/src/gallium/drivers/lima/lima_resource.h +mesa-21.0.0/src/gallium/drivers/lima/lima_screen.c +mesa-21.0.0/src/gallium/drivers/lima/lima_screen.h +mesa-21.0.0/src/gallium/drivers/lima/lima_state.c +mesa-21.0.0/src/gallium/drivers/lima/lima_texture.c +mesa-21.0.0/src/gallium/drivers/lima/lima_texture.h +mesa-21.0.0/src/gallium/drivers/lima/lima_util.c +mesa-21.0.0/src/gallium/drivers/lima/lima_util.h mesa-21.0.0/src/gallium/drivers/softpipe/sp_buffer.c mesa-21.0.0/src/gallium/drivers/softpipe/sp_buffer.h mesa-21.0.0/src/gallium/drivers/softpipe/sp_clear.c @@ -934,6 +995,8 @@ mesa-21.0.0/src/gallium/include/pipe/p_video_state.h mesa-21.0.0/src/gallium/targets/dri/target.c mesa-21.0.0/src/gallium/winsys/etnaviv/drm/etnaviv_drm_public.h mesa-21.0.0/src/gallium/winsys/etnaviv/drm/etnaviv_drm_winsys.c +mesa-21.0.0/src/gallium/winsys/lima/drm/lima_drm_winsys.c +mesa-21.0.0/src/gallium/winsys/lima/drm/lima_drm_public.h mesa-21.0.0/src/gallium/winsys/sw/dri/dri_sw_winsys.c mesa-21.0.0/src/gallium/winsys/sw/dri/dri_sw_winsys.h mesa-21.0.0/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.h @@ -1584,6 +1647,10 @@ mesa-21.0.0/src/mesa/x86/norm_args.h mesa-21.0.0/src/mesa/x86/sse.h mesa-21.0.0/src/mesa/x86/x86_xform.h mesa-21.0.0/src/mesa/x86/xform_args.h +mesa-21.0.0/src/panfrost/shared/pan_minmax_cache.c +mesa-21.0.0/src/panfrost/shared/pan_minmax_cache.h +mesa-21.0.0/src/panfrost/shared/pan_tiling.c +mesa-21.0.0/src/panfrost/shared/pan_tiling.h mesa-21.0.0/src/util/anon_file.h mesa-21.0.0/src/util/bigmath.h mesa-21.0.0/src/util/bitscan.h diff --git a/repos/libports/src/lib/mesa/lima/drm_init.cc b/repos/libports/src/lib/mesa/lima/drm_init.cc new file mode 100644 index 0000000000..53c9ab7e6f --- /dev/null +++ b/repos/libports/src/lib/mesa/lima/drm_init.cc @@ -0,0 +1,27 @@ +/** + * \brief Initialize DRM libraries session interface + * \author Josef Soentgen + * \date 2021-04-30 + */ + +/* + * Copyright (C) 2021-2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include <../include/util/list.h> +#include + +#include + +extern "C" { +#include +} + +void genode_drm_init(void) +{ + drm_init(Libdrm::Driver::LIMA); +} diff --git a/repos/libports/src/lib/mesa/lima/platform_lima.c b/repos/libports/src/lib/mesa/lima/platform_lima.c new file mode 100644 index 0000000000..ae0e1053e0 --- /dev/null +++ b/repos/libports/src/lib/mesa/lima/platform_lima.c @@ -0,0 +1,269 @@ +/** + * \brief lima (mali) EGL-DRI2 back end + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2021-04-30 + */ + +/* + * Copyright (C) 2021-2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ +/* + * Mesa + */ +#include +#include +/* + * Libc + */ +#include +#include + +/* + * Local + */ +#include + + +static int stride(int value) +{ + /* 32-bit RGB888 */ + return value * 4; +} + + +static void +dri2_genode_lima_put_image(__DRIdrawable * draw, int op, + int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); + struct Genode_egl_window *window = dri2_surf->g_win; + unsigned char *dst = window->addr; + + int src_stride; + int dst_stride = stride(dri2_surf->base.Width); + dri2_dpy->image->queryImage(dri2_surf->back_image, __DRI_IMAGE_ATTRIB_STRIDE, &src_stride); + + int copy_width = src_stride; + int x_offset = stride(x); + + dst += x_offset; + dst += y * dst_stride; + + /* copy width over stride boundary */ + if (copy_width > dst_stride - x_offset) + copy_width = dst_stride - x_offset; + + /* limit height */ + if (h > dri2_surf->base.Height - y) + h = dri2_surf->base.Height - y; + + /* copy to frame buffer and refresh */ + genode_blit(data, src_stride, dst, dst_stride, copy_width, h); +} + + +static EGLBoolean +dri2_genode_lima_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw) +{ + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); + + dri2_flush_drawable_for_swapbuffers(disp, draw); + dri2_dpy->flush->invalidate(dri2_surf->dri_drawable); + + _EGLContext *ctx = _eglGetCurrentContext(); + struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); + void *map_data = NULL; + int stride; + void *data = + dri2_dpy->image->mapImage(dri2_ctx->dri_context, dri2_surf->back_image, + 0, 0, + dri2_surf->base.Width, + dri2_surf->base.Height, + __DRI_IMAGE_TRANSFER_READ, &stride, + &map_data); + if (data) { + dri2_genode_lima_put_image(dri2_surf->dri_drawable, 0, 0, 0, + dri2_surf->base.Width, dri2_surf->base.Height, + (char *)data, (void *)dri2_surf); + + dri2_dpy->image->unmapImage(dri2_ctx->dri_context, + dri2_surf->back_image, map_data); + } + + return EGL_TRUE; +} + + +static struct dri2_egl_display_vtbl dri2_genode_display_vtbl = { + .authenticate = NULL, + .create_window_surface = dri2_genode_create_window_surface, + .create_pixmap_surface = dri2_genode_create_pixmap_surface, + .destroy_surface = dri2_genode_destroy_surface, + .swap_interval = dri2_genode_swap_interval, + .swap_buffers = dri2_genode_lima_swap_buffers, + .get_dri_drawable = dri2_surface_get_dri_drawable, +}; + + +static __DRIbuffer * +dri2_genode_get_buffers(__DRIdrawable * driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) +{ + _eglError(EGL_BAD_PARAMETER, "dri2_genode_get_buffers not implemented"); + *out_count = 0; + return NULL; +} + + +static void +dri2_genode_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) +{ + _eglError(EGL_BAD_PARAMETER, "dri2_genode_flush_front_buffer not implemented"); +} + + +static __DRIbuffer * +dri2_genode_get_buffers_with_format(__DRIdrawable * driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) +{ + _eglError(EGL_BAD_PARAMETER, "dri2_genode_get_buffers_with_format not implemented"); + *out_count = 0; + return NULL; +} + + +static int +dri2_genode_image_get_buffers(__DRIdrawable *driDrawable, + unsigned int format, + uint32_t *stamp, + void *loaderPrivate, + uint32_t buffer_mask, + struct __DRIimageList *buffers) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + + buffers->image_mask = 0; + buffers->front = NULL; + buffers->back = NULL; + + buffers->image_mask = __DRI_IMAGE_BUFFER_BACK; + buffers->back = dri2_surf->back_image; + + return 1; +} + + +static const __DRIdri2LoaderExtension dri2_loader_extension = { + .base = { __DRI_DRI2_LOADER, 3 }, + + .getBuffers = dri2_genode_get_buffers, + .flushFrontBuffer = dri2_genode_flush_front_buffer, + .getBuffersWithFormat = dri2_genode_get_buffers_with_format, +}; + + +static const __DRIimageLoaderExtension image_loader_extension = { + .base = { __DRI_IMAGE_LOADER, 1 }, + .getBuffers = dri2_genode_image_get_buffers, + .flushFrontBuffer = dri2_genode_flush_front_buffer, +}; + +static const __DRIextension *dri2_loader_extensions[] = { + &dri2_loader_extension.base, + &image_loader_extension.base, + &image_lookup_extension.base, + &background_callable_extension.base, + NULL, +}; + + + +static EGLBoolean dri2_initialize_genode_lima(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy; + static int rgb888_shifts[4] = { 16, 8, 0, 24 }; + static unsigned rgb888_sizes[4] = { 8, 8, 8, 8 }; + int i; + + /* initialize DRM back end */ + genode_drm_init(); + + dri2_dpy = calloc(1, sizeof *dri2_dpy); + if (!dri2_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + dri2_dpy->fd = 44; + dri2_dpy->driver_name = strdup("lima"); + + disp->DriverData = (void *)dri2_dpy; + if (!dri2_load_driver_dri3(disp)) + goto close_driver; + + dri2_dpy->dri2_major = 2; + dri2_dpy->dri2_minor = __DRI_DRI2_VERSION; + + dri2_dpy->loader_extensions = dri2_loader_extensions; + + /* + * The driver extensions are queried by the loader, where the + * extensions point to '__driDriverGetExtensions_lima' that + * in return is wraps the 'galliumdrm_driver_extensions'. + * The the third entry in the 'galliumdrm_driver_extensions' array + * points 'driDRI2Extension.base', which is the extension we are + * interested in. + * + * extern const __DRIextension **__driDriverGetExtensions_lima(void); + * dri2_dpy->driver_extensions = __driDriverGetExtensions_lima(); + */ + dri2_dpy->dri2 = (const __DRIdri2Extension*)dri2_dpy->driver_extensions[2]; + + if (!dri2_create_screen(disp)) + goto close_screen; + + if (!dri2_setup_extensions(disp)) + goto close_screen; + + dri2_setup_screen(disp); + + EGLint attrs[] = { + EGL_DEPTH_SIZE, 0, /* set in loop below (from DRI config) */ + EGL_NATIVE_VISUAL_TYPE, 0, + EGL_NATIVE_VISUAL_ID, 0, + EGL_NONE }; + + for (i = 0; dri2_dpy->driver_configs[i]; i++) { + /* set depth size in attrs */ + attrs[1] = dri2_dpy->driver_configs[i]->modes.depthBits; + dri2_add_config(disp, dri2_dpy->driver_configs[i], i, + EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT, + attrs, rgb888_shifts, rgb888_sizes); + } + + dri2_dpy->vtbl = &dri2_genode_display_vtbl; + + return EGL_TRUE; + +close_screen: + dlclose(dri2_dpy->driver); +close_driver: + free(dri2_dpy); + + return EGL_FALSE; +} + + +EGLBoolean dri2_initialize_genode_backend(_EGLDisplay *disp) +{ + return dri2_initialize_genode_lima(disp); +} diff --git a/repos/libports/src/lib/mesa/lima/target.mk b/repos/libports/src/lib/mesa/lima/target.mk new file mode 100644 index 0000000000..cff12952c1 --- /dev/null +++ b/repos/libports/src/lib/mesa/lima/target.mk @@ -0,0 +1,3 @@ +REQUIRES := arm_v8a +TARGET := dummy-mesa_gpu-lima +LIBS := mesa_gpu-lima diff --git a/repos/libports/src/lib/mesa/patches/lima.patch b/repos/libports/src/lib/mesa/patches/lima.patch new file mode 100644 index 0000000000..a8cc8a9243 --- /dev/null +++ b/repos/libports/src/lib/mesa/patches/lima.patch @@ -0,0 +1,12 @@ +--- a/src/lib/mesa/src/loader/loader.c +--- b/src/lib/mesa/src/loader/loader.c +@@ -473,6 +473,9 @@ + if (fd == 43) { + return strdup("iris"); + } ++ if (fd == 44) { ++ return strdup("lima"); ++ } + char *driver; + + /* Allow an environment variable to force choosing a different driver diff --git a/repos/libports/src/lib/mesa/patches/sync_wait.patch b/repos/libports/src/lib/mesa/patches/sync_wait.patch new file mode 100644 index 0000000000..e64e0754f2 --- /dev/null +++ b/repos/libports/src/lib/mesa/patches/sync_wait.patch @@ -0,0 +1,20 @@ +--- a/src/lib/mesa/src/util/libsync.h ++++ b/src/lib/mesa/src/util/libsync.h +@@ -65,6 +65,8 @@ + #define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data) + #endif + ++extern int drm_poll(struct pollfd *, nfds_t, int); ++ + static inline int sync_wait(int fd, int timeout) + { + struct pollfd fds = {0}; +@@ -74,7 +76,7 @@ + fds.events = POLLIN; + + do { +- ret = poll(&fds, 1, timeout); ++ ret = drm_poll(&fds, 1, timeout); + if (ret > 0) { + if (fds.revents & (POLLERR | POLLNVAL)) { + errno = EINVAL;