libports: add mesa/lima driver

This commit introduces the Mesa3D lima driver for Mali 400 series
GPUs.

Issue #4559.
This commit is contained in:
Josef Söntgen 2022-07-07 17:35:21 +02:00 committed by Christian Helmuth
parent d2c26fd504
commit da25b288ee
19 changed files with 1408 additions and 11 deletions

View File

@ -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);

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 :=

View File

@ -1 +1 @@
2a8726a52ca7b243fcf40d07da28a52aba4c767f
a195203391df18dabe0e9c247301d9f3df1c8192

View File

@ -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

View File

@ -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

View File

@ -2,3 +2,4 @@ base
gpu_session
libc
vfs_gpu
mesa

View File

@ -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 \

View File

@ -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;
}
}

View File

@ -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 <base/attached_dataspace.h>
#include <base/debug.h>
#include <base/heap.h>
#include <base/log.h>
#include <gpu_session/connection.h>
#include <gpu/info_lima.h>
#include <util/string.h>
#include <vfs_gpu.h>
extern "C" {
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#include <drm.h>
#include <drm-uapi/lima_drm.h>
#include <libdrm_macros.h>
}
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 "<non-DRM>";
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 "<unknown drm>";
}
}
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 "<unknown driver>";
}
}
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 <typename FN, typename T> 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<void const*>(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<Gpu::Buffer>::Element const _elem;
Genode::Dataspace_capability const cap;
size_t const size;
Genode::Constructible<Genode::Attached_dataspace> _attached_buffer { };
Buffer(Gpu::Connection &gpu,
size_t size,
Genode::Id_space<Gpu::Buffer> &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<addr_t>(_attached_buffer->local_addr<addr_t>());
}
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<Gpu_context>;
Id_space::Element const _elem;
Gpu_context(int fd, unsigned long gpu,
Genode::Id_space<Gpu_context> &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>;
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 '<gpu>' 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<Syncobj>;
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> _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 '<gpu>' 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<Gpu::Info_lima>() };
Id_space<Buffer> _buffer_space { };
/*
* Play it safe, glmark2 apparently submits araound 110 KiB at
* some point.
*/
enum { EXEC_BUFFER_SIZE = 256u << 10 };
Constructible<Buffer> _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>(syncobj_id, wait);
} catch (Genode::Id_space<Lima::Call::Syncobj>::Unknown_id) { }
}
template <typename FN>
bool _apply_handle(uint32_t handle, FN const &fn)
{
Buffer_id const id { .value = handle };
bool found = false;
_buffer_space.apply<Buffer>(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 <typename FUNC>
void _alloc_buffer(::uint64_t const size, FUNC const &fn)
{
size_t donate = size;
Buffer *buffer = nullptr;
retry<Gpu::Session::Out_of_ram>(
[&] () {
retry<Gpu::Session::Out_of_caps>(
[&] () {
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>(syncobj_id, [&] (Syncobj &sync_obj) {
_gpu_context_space.apply<Gpu_context>(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<Gpu_context>(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<drm_lima_ctx_create*>(arg));
case DRM_LIMA_CTX_FREE:
return _drm_lima_ctx_free(*reinterpret_cast<drm_lima_ctx_free*>(arg));
case DRM_LIMA_GEM_INFO:
return _drm_lima_gem_info(*reinterpret_cast<drm_lima_gem_info*>(arg));
case DRM_LIMA_GEM_CREATE:
return _drm_lima_gem_create(*reinterpret_cast<drm_lima_gem_create*>(arg));
case DRM_LIMA_GEM_SUBMIT:
return _drm_lima_gem_submit(*reinterpret_cast<drm_lima_gem_submit*>(arg));
case DRM_LIMA_GEM_WAIT:
return _drm_lima_gem_wait(*reinterpret_cast<drm_lima_gem_wait*>(arg));
case DRM_LIMA_GET_PARAM:
return _drm_lima_get_param(*reinterpret_cast<drm_lima_get_param*>(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<Syncobj>(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<drm_gem_close*>(arg));
case command_number(DRM_IOCTL_VERSION):
return _drm_version(*reinterpret_cast<drm_version*>(arg));
case command_number(DRM_IOCTL_SYNCOBJ_CREATE):
return _drm_syncobj_create(*reinterpret_cast<drm_syncobj_create*>(arg));
case command_number(DRM_IOCTL_SYNCOBJ_DESTROY):
return _drm_syncobj_destroy(*reinterpret_cast<drm_syncobj_destroy*>(arg));
case command_number(DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD):
return _drm_syncobj_handle_to_fd(*reinterpret_cast<drm_syncobj_handle*>(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>([&] (Gpu_context &ctx) {
Genode::destroy(_heap, &ctx); })) { ; }
while (_syncobj_space.apply_any<Syncobj>([&] (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<Lima::Call> _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 '<gpu>' 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;
}

View File

@ -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

View File

@ -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 <base/env.h>
#include <libdrm/ioctl_dispatch.h>
extern "C" {
#include <platform.h>
}
void genode_drm_init(void)
{
drm_init(Libdrm::Driver::LIMA);
}

View File

@ -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 <egl_dri2.h>
#include <drivers/dri/common/utils.h>
/*
* Libc
*/
#include <string.h>
#include <dlfcn.h>
/*
* Local
*/
#include <platform.h>
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);
}

View File

@ -0,0 +1,3 @@
REQUIRES := arm_v8a
TARGET := dummy-mesa_gpu-lima
LIBS := mesa_gpu-lima

View File

@ -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

View File

@ -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;