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;