Remove incomplete NX support

Update submodules & tracking branches
This commit is contained in:
Luke Street 2021-04-06 12:54:06 -04:00
parent 771dbaf1aa
commit bb6274e638
21 changed files with 4 additions and 4372 deletions

8
.gitmodules vendored
View File

@ -1,12 +1,8 @@
[submodule "glslang"]
path = glslang
url = https://github.com/KhronosGroup/glslang.git
branch = master
[submodule "logvisor"]
path = logvisor
url = ../logvisor.git
[submodule "lib/graphicsdev/nx/mesa"]
path = lib/graphicsdev/nx/mesa
url = ../mesa.git
[submodule "lib/graphicsdev/nx/libdrm_nouveau"]
path = lib/graphicsdev/nx/libdrm_nouveau
url = https://github.com/devkitPro/libdrm_nouveau.git
branch = master

View File

@ -93,11 +93,6 @@ target_include_directories(boo PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
add_subdirectory(lib/graphicsdev/nx)
if(TARGET nx_compiler)
target_compile_definitions(boo PUBLIC -DHECL_NOUVEAU_NX=1)
endif()
if(NOT GEKKO AND NOT CAFE AND NOT WINDOWS_STORE AND NOT NX)
add_library(glew lib/graphicsdev/glew.c)
# For some reason, clang takes forever if glew.c is not built with -Os
@ -265,16 +260,6 @@ elseif(APPLE)
${METAL_LIBRARY}
${QUARTZCORE_LIBRARY}
)
elseif(NX)
target_compile_definitions(boo PUBLIC -DBOO_HAS_NX=1)
target_sources(boo PRIVATE
lib/nx/ApplicationNX.cpp
lib/nx/WindowNX.cpp
lib/audiodev/AudioMatrix.cpp
lib/inputdev/HIDListenerNX.cpp
lib/inputdev/HIDDeviceNX.cpp
)
target_link_libraries(boo PUBLIC nx_runtime)
else(NOT GEKKO)
target_sources(boo PRIVATE
lib/audiodev/LinuxMidi.hpp

View File

@ -44,7 +44,7 @@ public:
void deviceError(const S& format, Args&&... args) {
vdeviceError(fmt::to_string_view<Char>(format),
fmt::basic_format_args<fmt::buffer_context<Char>>(
fmt::internal::make_args_checked<Args...>(format, args...)));
fmt::make_args_checked<Args...>(format, args...)));
}
virtual void initialCycle() {}
virtual void transferCycle() {}

View File

@ -1,154 +0,0 @@
option(ENABLE_NX "Build mesa for offline NX shader compilation and runtime" OFF)
find_program(MESON_PROG meson)
find_program(NINJA_PROG ninja)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/mesa/meson.build AND
EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/libdrm_nouveau/Makefile AND
MESON_PROG AND NINJA_PROG AND ENABLE_NX)
message(STATUS "Enabling NX support")
set(LIBDRM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libdrm_nouveau)
set(MESA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mesa)
set(MESA_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/mesa)
file(MAKE_DIRECTORY ${MESA_BUILD_DIR})
if(NOT NX)
set(PLAT_MESA_TARGETS src/mesa/libmesa_sse41.a)
else()
set(PLAT_MESA_TARGETS src/gallium/winsys/nouveau/switch/libnouveauwinsys.a)
endif()
set(MESA_TARGETS
src/compiler/libcompiler.a
src/compiler/glsl/libglsl.a
src/compiler/glsl/glcpp/libglcpp.a
src/compiler/nir/libnir.a
src/libglsl_util.a
src/util/libmesa_util.a
src/mesa/libmesa_gallium.a
${PLAT_MESA_TARGETS}
src/gallium/auxiliary/libgallium.a
src/gallium/auxiliary/libgalliumvl.a
src/gallium/drivers/nouveau/libnouveau.a)
include_directories(
${MESA_DIR}/include
${MESA_DIR}/src
${MESA_DIR}/src/mesa
${MESA_DIR}/src/mapi
${MESA_DIR}/src/compiler/glsl
${MESA_BUILD_DIR}/src/compiler
${MESA_DIR}/src/mesa/state_tracker
${MESA_DIR}/src/gallium/include
${MESA_DIR}/src/gallium/auxiliary
${MESA_DIR}/src/gallium/drivers/nouveau
${LIBDRM_DIR}/include)
if(${CMAKE_BUILD_TYPE} STREQUAL Release OR ${CMAKE_BUILD_TYPE} STREQUAL RelWithDebInfo)
set(MESON_BUILD_TYPE release)
set(MESON_SANITIZE_ARGS "")
else()
set(MESON_BUILD_TYPE debug)
set(MESON_SANITIZE_ARGS "-fsanitize=address")
endif()
if(NX)
configure_file(switch_cross_file.txt.in switch_cross_file.txt)
set(MESON_CROSS --cross-file ${CMAKE_CURRENT_BINARY_DIR}/switch_cross_file.txt -D c_std=gnu11 -D cpp_std=gnu++17)
set(MESA_PLATFORMS switch)
endif()
if(NOT EXISTS ${MESA_BUILD_DIR}/build.ninja)
message(STATUS "Preparing mesa build system")
set(ENV{CC} "")
set(ENV{CXX} "")
execute_process(COMMAND ${MESON_PROG} setup -D buildtype=${MESON_BUILD_TYPE} ${MESON_CROSS}
-D gallium-drivers=nouveau -D dri-drivers= -D vulkan-drivers= -D llvm=false
-D shared-glapi=true -D gles1=false -D gles2=false -D gbm=false
-D shader-cache=false -D boo-offline-mode=true -D "platforms=${MESA_PLATFORMS}" -D glx=disabled
-D "c_args=${MESON_SANITIZE_ARGS} -I${LIBDRM_DIR}/include -DDEBUG=1 -DHAVE_LIBDRM"
-D "cpp_args=${MESON_SANITIZE_ARGS} -I${LIBDRM_DIR}/include -DDEBUG=1 -DHAVE_LIBDRM"
-D "c_link_args=${MESON_SANITIZE_ARGS}"
-D "cpp_link_args=${MESON_SANITIZE_ARGS}"
${MESA_DIR} ${MESA_BUILD_DIR}
RESULT_VARIABLE MESON_RESULT)
if(NOT MESON_RESULT EQUAL 0)
message(FATAL_ERROR "meson failed with error code ${MESON_RESULT}")
endif()
endif()
message(STATUS "Invoking mesa build system")
execute_process(COMMAND ${NINJA_PROG} -C ${MESA_BUILD_DIR} ${MESA_TARGETS} RESULT_VARIABLE NINJA_RESULT)
if(NOT NINJA_RESULT EQUAL 0)
message(FATAL_ERROR "ninja failed with error code ${NINJA_RESULT}")
endif()
if(NOT WIN32)
add_definitions("-DHAVE_PTHREAD -DHAVE_TIMESPEC_GET")
if(${CMAKE_SYSTEM_NAME} STREQUAL Linux)
add_definitions("-DHAVE_LINUX_FUTEX_H")
endif()
endif()
add_definitions("-DHAVE_ZLIB -DDEBUG=1 -DHAVE_LIBDRM")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=return-type")
add_subdirectory(fake_libdrm_nouveau)
add_library(nx_compiler nx_compiler.cpp
${MESA_DIR}/src/compiler/glsl/ir_builder_print_visitor.cpp)
target_link_libraries(nx_compiler
${MESA_BUILD_DIR}/src/mesa/libmesa_gallium.a
${MESA_BUILD_DIR}/src/mesa/libmesa_sse41.a
${MESA_BUILD_DIR}/src/compiler/nir/libnir.a
${MESA_BUILD_DIR}/src/compiler/glsl/libglsl.a
${MESA_BUILD_DIR}/src/libglsl_util.a
${MESA_BUILD_DIR}/src/compiler/glsl/glcpp/libglcpp.a
${MESA_BUILD_DIR}/src/compiler/libcompiler.a
${MESA_BUILD_DIR}/src/gallium/drivers/nouveau/libnouveau.a
${MESA_BUILD_DIR}/src/gallium/auxiliary/libgallium.a
${MESA_BUILD_DIR}/src/gallium/auxiliary/libgalliumvl.a
${MESA_BUILD_DIR}/src/util/libmesa_util.a
fake_libdrm_nouveau
unwind dl pthread z)
add_executable(nx_compiler_driver nx_compiler_driver.cpp)
target_link_libraries(nx_compiler_driver nx_compiler)
if(COMMAND add_sanitizers)
add_sanitizers(nx_compiler nx_compiler_driver)
endif()
if(NX)
include_directories(${DEVKITPRO}/libnx/include)
add_library(libdrm_nouveau
libdrm_nouveau/source/bomap.c
libdrm_nouveau/source/bufctx.c
libdrm_nouveau/source/nouveau.c
libdrm_nouveau/source/pushbuf.c)
add_definitions(-DBOO_HAS_NX=1)
add_library(nx_runtime NX.cpp nx_compiler.cpp
${MESA_DIR}/src/compiler/glsl/ir_builder_print_visitor.cpp)
target_link_libraries(nx_runtime xxhash
${MESA_BUILD_DIR}/src/mesa/libmesa_gallium.a
${MESA_BUILD_DIR}/src/compiler/nir/libnir.a
${MESA_BUILD_DIR}/src/compiler/glsl/libglsl.a
${MESA_BUILD_DIR}/src/libglsl_util.a
${MESA_BUILD_DIR}/src/compiler/glsl/glcpp/libglcpp.a
${MESA_BUILD_DIR}/src/compiler/libcompiler.a
${MESA_BUILD_DIR}/src/gallium/drivers/nouveau/libnouveau.a
${MESA_BUILD_DIR}/src/gallium/winsys/nouveau/switch/libnouveauwinsys.a
${MESA_BUILD_DIR}/src/gallium/auxiliary/libgallium.a
${MESA_BUILD_DIR}/src/gallium/auxiliary/libgalliumvl.a
${MESA_BUILD_DIR}/src/util/libmesa_util.a
libdrm_nouveau nx)
if(COMMAND add_sanitizers)
add_sanitizers(nx_runtime libdrm_nouveau)
endif()
endif()
else()
if(NX)
message(FATAL_ERROR "Unable to find meson or ninja or mesa submodules; this is required for NX.")
elseif(ENABLE_NX)
message(STATUS "Unable to find meson or ninja or mesa submodules; skipping NX support.")
endif()
endif()

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
add_library(fake_libdrm_nouveau nouveau.c pushbuf.c bufctx.c bomap.c)

View File

@ -1,123 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "private.h"
#ifdef DEBUG
# define TRACE(x...) printf("nouveau: " x)
# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
#else
# define TRACE(x...)
# define CALLED()
#endif
static inline unsigned bo_map_hash(struct nouveau_bo *bo)
{
return bo->handle % BO_MAP_NUM_BUCKETS;
}
static inline struct nouveau_client_bo_map_entry *bo_map_lookup(struct nouveau_client_bo_map *bomap, struct nouveau_bo *bo)
{
struct nouveau_client_bo_map_entry *ent;
for (ent = bomap->buckets[bo_map_hash(bo)]; ent; ent = ent->next)
if (ent->bo_handle == bo->handle)
break;
return ent;
}
void
cli_map_free(struct nouveau_client *client)
{
struct nouveau_client_bo_map *bomap = &nouveau_client(client)->bomap;
unsigned i;
// Free all buckets
for (i = 0; i < BO_MAP_NUM_BUCKETS+1; i ++) {
struct nouveau_client_bo_map_entry *ent, *next;
for (ent = bomap->buckets[i]; ent; ent = next) {
next = ent->next;
free(ent);
}
}
}
struct drm_nouveau_gem_pushbuf_bo *
cli_kref_get(struct nouveau_client *client, struct nouveau_bo *bo)
{
struct nouveau_client_bo_map *bomap = &nouveau_client(client)->bomap;
struct nouveau_client_bo_map_entry *ent = bo_map_lookup(bomap, bo);
struct drm_nouveau_gem_pushbuf_bo *kref = NULL;
if (ent)
kref = ent->kref;
return kref;
}
struct nouveau_pushbuf *
cli_push_get(struct nouveau_client *client, struct nouveau_bo *bo)
{
struct nouveau_client_bo_map *bomap = &nouveau_client(client)->bomap;
struct nouveau_client_bo_map_entry *ent = bo_map_lookup(bomap, bo);
struct nouveau_pushbuf *push = NULL;
if (ent)
push = ent->push;
return push;
}
static struct nouveau_client_bo_map_entry *bo_map_get_free(struct nouveau_client_bo_map *bomap)
{
// Try to find an entry first in the bucket of free entries,
// and if said bucket is empty then allocate a new entry
struct nouveau_client_bo_map_entry *ent = bomap->buckets[BO_MAP_NUM_BUCKETS];
if (ent)
bomap->buckets[BO_MAP_NUM_BUCKETS] = ent->next;
else
ent = malloc(sizeof(*ent));
return ent;
}
void
cli_kref_set(struct nouveau_client *client, struct nouveau_bo *bo,
struct drm_nouveau_gem_pushbuf_bo *kref,
struct nouveau_pushbuf *push)
{
struct nouveau_client_bo_map *bomap = &nouveau_client(client)->bomap;
struct nouveau_client_bo_map_entry *ent = bo_map_lookup(bomap, bo);
TRACE("setting 0x%x <-- {%p,%p}\n", bo->handle, kref, push);
if (!ent) {
// Do nothing if the user wanted to free the entry anyway
if (!kref && !push)
return;
// Try to get a free entry for this bo
ent = bo_map_get_free(bomap);
if (!ent) {
// Shouldn't we panic here?
TRACE("panic: out of memory\n");
return;
}
// Add entry to bucket list
unsigned hash = bo_map_hash(bo);
ent->next = bomap->buckets[hash];
if (ent->next)
ent->next->prev_next = &ent->next;
ent->prev_next = &bomap->buckets[hash];
ent->bo_handle = bo->handle;
bomap->buckets[hash] = ent;
}
if (kref || push) {
// Update the entry
ent->kref = kref;
ent->push = push;
}
else {
// Unlink the entry, and put it in the bucket of free entries
*ent->prev_next = ent->next;
if (ent->next)
ent->next->prev_next = ent->prev_next;
ent->next = bomap->buckets[BO_MAP_NUM_BUCKETS];
bomap->buckets[BO_MAP_NUM_BUCKETS] = ent;
}
}

View File

@ -1,163 +0,0 @@
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include <errno.h>
#include "libdrm_lists.h"
#include "nouveau.h"
#include "private.h"
struct nouveau_bufref_priv {
struct nouveau_bufref base;
struct nouveau_bufref_priv *next;
struct nouveau_bufctx *bufctx;
};
struct nouveau_bufbin_priv {
struct nouveau_bufref_priv *list;
int relocs;
};
struct nouveau_bufctx_priv {
struct nouveau_bufctx base;
struct nouveau_bufref_priv *free;
int nr_bins;
struct nouveau_bufbin_priv bins[];
};
static inline struct nouveau_bufctx_priv *
nouveau_bufctx(struct nouveau_bufctx *bctx)
{
return (struct nouveau_bufctx_priv *)bctx;
}
int
nouveau_bufctx_new(struct nouveau_client *client, int bins,
struct nouveau_bufctx **pbctx)
{
struct nouveau_bufctx_priv *priv;
priv = calloc(1, sizeof(*priv) + sizeof(priv->bins[0]) * bins);
if (priv) {
DRMINITLISTHEAD(&priv->base.head);
DRMINITLISTHEAD(&priv->base.pending);
DRMINITLISTHEAD(&priv->base.current);
priv->base.client = client;
priv->nr_bins = bins;
*pbctx = &priv->base;
return 0;
}
return -ENOMEM;
}
void
nouveau_bufctx_del(struct nouveau_bufctx **pbctx)
{
struct nouveau_bufctx_priv *pctx = nouveau_bufctx(*pbctx);
struct nouveau_bufref_priv *pref;
if (pctx) {
while (pctx->nr_bins--)
nouveau_bufctx_reset(&pctx->base, pctx->nr_bins);
while ((pref = pctx->free)) {
pctx->free = pref->next;
free(pref);
}
free(pctx);
*pbctx = NULL;
}
}
void
nouveau_bufctx_reset(struct nouveau_bufctx *bctx, int bin)
{
struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
struct nouveau_bufref_priv *pref;
while ((pref = pbin->list)) {
DRMLISTDELINIT(&pref->base.thead);
pbin->list = pref->next;
pref->next = pctx->free;
pctx->free = pref;
}
bctx->relocs -= pbin->relocs;
pbin->relocs = 0;
}
struct nouveau_bufref *
nouveau_bufctx_refn(struct nouveau_bufctx *bctx, int bin,
struct nouveau_bo *bo, uint32_t flags)
{
struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
struct nouveau_bufref_priv *pref = pctx->free;
if (!pref)
pref = malloc(sizeof(*pref));
else
pctx->free = pref->next;
if (pref) {
pref->base.bo = bo;
pref->base.flags = flags;
pref->base.packet = 0;
DRMLISTADDTAIL(&pref->base.thead, &bctx->pending);
pref->bufctx = bctx;
pref->next = pbin->list;
pbin->list = pref;
}
return &pref->base;
}
struct nouveau_bufref *
nouveau_bufctx_mthd(struct nouveau_bufctx *bctx, int bin, uint32_t packet,
struct nouveau_bo *bo, uint64_t data, uint32_t flags,
uint32_t vor, uint32_t tor)
{
struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
struct nouveau_bufref *bref = nouveau_bufctx_refn(bctx, bin, bo, flags);
if (bref) {
bref->packet = packet;
bref->data = data;
bref->vor = vor;
bref->tor = tor;
pbin->relocs++;
bctx->relocs++;
}
return bref;
}

View File

@ -1,17 +0,0 @@
#ifndef LIBDRM_ATOMICS_H
#define LIBDRM_ATOMICS_H
typedef struct {
int atomic;
} atomic_t;
# define atomic_read(x) ((x)->atomic)
# define atomic_set(x, val) ((x)->atomic = (val))
# define atomic_inc(x) ((void) __sync_fetch_and_add (&(x)->atomic, 1))
# define atomic_inc_return(x) (__sync_add_and_fetch (&(x)->atomic, 1))
# define atomic_dec_and_test(x) (__sync_add_and_fetch (&(x)->atomic, -1) == 0)
# define atomic_add(x, v) ((void) __sync_add_and_fetch(&(x)->atomic, (v)))
# define atomic_dec(x, v) ((void) __sync_sub_and_fetch(&(x)->atomic, (v)))
# define atomic_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (&(x)->atomic, oldv, newv)
#endif

View File

@ -1,118 +0,0 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*/
/*
* List macros heavily inspired by the Linux kernel
* list handling. No list looping yet.
*/
#include <stddef.h>
typedef struct _drmMMListHead
{
struct _drmMMListHead *prev;
struct _drmMMListHead *next;
} drmMMListHead;
#define DRMINITLISTHEAD(__item) \
do{ \
(__item)->prev = (__item); \
(__item)->next = (__item); \
} while (0)
#define DRMLISTADD(__item, __list) \
do { \
(__item)->prev = (__list); \
(__item)->next = (__list)->next; \
(__list)->next->prev = (__item); \
(__list)->next = (__item); \
} while (0)
#define DRMLISTADDTAIL(__item, __list) \
do { \
(__item)->next = (__list); \
(__item)->prev = (__list)->prev; \
(__list)->prev->next = (__item); \
(__list)->prev = (__item); \
} while(0)
#define DRMLISTDEL(__item) \
do { \
(__item)->prev->next = (__item)->next; \
(__item)->next->prev = (__item)->prev; \
} while(0)
#define DRMLISTDELINIT(__item) \
do { \
(__item)->prev->next = (__item)->next; \
(__item)->next->prev = (__item)->prev; \
(__item)->next = (__item); \
(__item)->prev = (__item); \
} while(0)
#define DRMLISTENTRY(__type, __item, __field) \
((__type *)(((char *) (__item)) - offsetof(__type, __field)))
#define DRMLISTEMPTY(__item) ((__item)->next == (__item))
#define DRMLISTSINGLE(__list) \
(!DRMLISTEMPTY(__list) && ((__list)->next == (__list)->prev))
#define DRMLISTFOREACH(__item, __list) \
for ((__item) = (__list)->next; \
(__item) != (__list); (__item) = (__item)->next)
#define DRMLISTFOREACHSAFE(__item, __temp, __list) \
for ((__item) = (__list)->next, (__temp) = (__item)->next; \
(__item) != (__list); \
(__item) = (__temp), (__temp) = (__item)->next)
#define DRMLISTFOREACHSAFEREVERSE(__item, __temp, __list) \
for ((__item) = (__list)->prev, (__temp) = (__item)->prev; \
(__item) != (__list); \
(__item) = (__temp), (__temp) = (__item)->prev)
#define DRMLISTFOREACHENTRY(__item, __list, __head) \
for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head); \
&(__item)->__head != (__list); \
(__item) = DRMLISTENTRY(typeof(*__item), \
(__item)->__head.next, __head))
#define DRMLISTFOREACHENTRYSAFE(__item, __temp, __list, __head) \
for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head), \
(__temp) = DRMLISTENTRY(typeof(*__item), \
(__item)->__head.next, __head); \
&(__item)->__head != (__list); \
(__item) = (__temp), \
(__temp) = DRMLISTENTRY(typeof(*__item), \
(__temp)->__head.next, __head))
#define DRMLISTJOIN(__list, __join) if (!DRMLISTEMPTY(__list)) { \
(__list)->next->prev = (__join); \
(__list)->prev->next = (__join)->next; \
(__join)->next->prev = (__list)->prev; \
(__join)->next = (__list)->next; \
}

View File

@ -1,419 +0,0 @@
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <malloc.h>
#include "libdrm_lists.h"
#include "libdrm_atomics.h"
#include "nouveau_drm.h"
#include "nouveau.h"
#include "private.h"
#include "nvif/class.h"
#include "nvif/cl0080.h"
#include "nvif/ioctl.h"
#include "nvif/unpack.h"
#ifdef DEBUG
# define TRACE(x...) printf("nouveau: " x)
# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
#else
# define TRACE(x...)
# define CALLED()
#endif
/* Unused
int
nouveau_object_mthd(struct nouveau_object *obj,
uint32_t mthd, void *data, uint32_t size)
{
return 0;
}
*/
/* Unused
void
nouveau_object_sclass_put(struct nouveau_sclass **psclass)
{
}
*/
/* Unused
int
nouveau_object_sclass_get(struct nouveau_object *obj,
struct nouveau_sclass **psclass)
{
return 0;
}
*/
int
nouveau_object_mclass(struct nouveau_object *obj,
const struct nouveau_mclass *mclass)
{
// TODO: Only used for VP3 firmware upload
CALLED();
return 0;
}
/* NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX */
int
nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
uint32_t oclass, void *data, uint32_t length,
struct nouveau_object **pobj)
{
struct nouveau_object *obj;
CALLED();
if (!(obj = calloc(1, sizeof(*obj))))
return -ENOMEM;
if (oclass == NOUVEAU_FIFO_CHANNEL_CLASS)
{
struct nouveau_fifo *fifo;
if (!(fifo = calloc(1, sizeof(*fifo)))) {
free(obj);
return -ENOMEM;
}
fifo->object = parent;
fifo->channel = 0;
fifo->pushbuf = 0;
obj->data = fifo;
obj->length = sizeof(*fifo);
}
obj->parent = parent;
obj->oclass = oclass;
*pobj = obj;
return 0;
}
/* NVGPU_IOCTL_CHANNEL_FREE_OBJ_CTX */
void
nouveau_object_del(struct nouveau_object **pobj)
{
CALLED();
if (!pobj)
return;
struct nouveau_object *obj = *pobj;
if (!obj)
return;
if (obj->data)
free(obj->data);
free(obj);
*pobj = NULL;
}
void
nouveau_drm_del(struct nouveau_drm **pdrm)
{
CALLED();
struct nouveau_drm *drm = *pdrm;
free(drm);
*pdrm = NULL;
}
int
nouveau_drm_new(int fd, struct nouveau_drm **pdrm)
{
CALLED();
struct nouveau_drm *drm;
if (!(drm = calloc(1, sizeof(*drm)))) {
return -ENOMEM;
}
drm->fd = fd;
*pdrm = drm;
return 0;
}
int
nouveau_device_new(struct nouveau_object *parent, int32_t oclass,
void *data, uint32_t size, struct nouveau_device **pdev)
{
struct nouveau_drm *drm = nouveau_drm(parent);
struct nouveau_device_priv *nvdev;
//Result rc;
CALLED();
if (!(nvdev = calloc(1, sizeof(*nvdev))))
return -ENOMEM;
*pdev = &nvdev->base;
nvdev->base.object.parent = &drm->client;
nvdev->base.object.handle = ~0ULL;
nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS;
nvdev->base.object.length = ~0;
nvdev->base.chipset = 0x120; // NVGPU_GPU_ARCH_GM200
return 0;
}
void
nouveau_device_del(struct nouveau_device **pdev)
{
CALLED();
struct nouveau_device_priv *nvdev = nouveau_device(*pdev);
if (nvdev) {
free(nvdev->client);
free(nvdev);
*pdev = NULL;
}
}
int
nouveau_getparam(struct nouveau_device *dev, uint64_t param, uint64_t *value)
{
/* NOUVEAU_GETPARAM_PTIMER_TIME = NVGPU_GPU_IOCTL_GET_GPU_TIME */
return 0;
}
/* Unused
int
nouveau_setparam(struct nouveau_device *dev, uint64_t param, uint64_t value)
{
return 0;
}
*/
int
nouveau_client_new(struct nouveau_device *dev, struct nouveau_client **pclient)
{
struct nouveau_device_priv *nvdev = nouveau_device(dev);
struct nouveau_client_priv *pcli;
int id = 0, i, ret = -ENOMEM;
uint32_t *clients;
CALLED();
for (i = 0; i < nvdev->nr_client; i++) {
id = ffs(nvdev->client[i]) - 1;
if (id >= 0)
goto out;
}
clients = realloc(nvdev->client, sizeof(uint32_t) * (i + 1));
if (!clients)
goto unlock;
nvdev->client = clients;
nvdev->client[i] = 0;
nvdev->nr_client++;
out:
pcli = calloc(1, sizeof(*pcli));
if (pcli) {
nvdev->client[i] |= (1 << id);
pcli->base.device = dev;
pcli->base.id = (i * 32) + id;
ret = 0;
}
*pclient = &pcli->base;
unlock:
return ret;
}
void
nouveau_client_del(struct nouveau_client **pclient)
{
struct nouveau_client_priv *pcli = nouveau_client(*pclient);
struct nouveau_device_priv *nvdev;
CALLED();
if (pcli) {
int id = pcli->base.id;
nvdev = nouveau_device(pcli->base.device);
nvdev->client[id / 32] &= ~(1 << (id % 32));
cli_map_free(&pcli->base);
free(pcli);
}
}
static void
nouveau_bo_del(struct nouveau_bo *bo)
{
CALLED();
struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
free(nvbo);
}
/* Fake mapped data to dereference without crashing
* Value of 1 to indicate signalled fence sequence counter */
static uint32_t MapData = 1;
int
nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, uint32_t align,
uint64_t size, union nouveau_bo_config *config,
struct nouveau_bo **pbo)
{
CALLED();
struct nouveau_device_priv *nvdev = nouveau_device(dev);
struct nouveau_bo_priv *nvbo = calloc(1, sizeof(*nvbo));
struct nouveau_bo *bo = &nvbo->base;
nvbo->map_addr = &MapData;
atomic_set(&nvbo->refcnt, 1);
*pbo = bo;
return 0;
}
/* Unused
static int
nouveau_bo_wrap_locked(struct nouveau_device *dev, uint32_t handle,
struct nouveau_bo **pbo, int name)
{
return 0;
}
static void
nouveau_bo_make_global(struct nouveau_bo_priv *nvbo)
{
}
*/
int
nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle,
struct nouveau_bo **pbo)
{
// TODO: NV30-only
CALLED();
return 0;
}
int
nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name,
struct nouveau_bo **pbo)
{
CALLED();
struct nouveau_device_priv *nvdev = nouveau_device(dev);
struct nouveau_bo_priv *nvbo = calloc(1, sizeof(*nvbo));
struct nouveau_bo *bo = &nvbo->base;
atomic_set(&nvbo->refcnt, 1);
*pbo = bo;
return 0;
}
int
nouveau_bo_name_get(struct nouveau_bo *bo, uint32_t *name)
{
// TODO: Unimplemented
CALLED();
return 0;
}
void
nouveau_bo_ref(struct nouveau_bo *bo, struct nouveau_bo **pref)
{
CALLED();
struct nouveau_bo *ref = *pref;
if (bo) {
atomic_inc(&nouveau_bo(bo)->refcnt);
}
if (ref) {
if (atomic_dec_and_test(&nouveau_bo(ref)->refcnt))
nouveau_bo_del(ref);
}
*pref = bo;
}
int
nouveau_bo_prime_handle_ref(struct nouveau_device *dev, int prime_fd,
struct nouveau_bo **bo)
{
// TODO: Unimplemented
CALLED();
return 0;
}
int
nouveau_bo_set_prime(struct nouveau_bo *bo, int *prime_fd)
{
// TODO: Unimplemented
CALLED();
return 0;
}
int
nouveau_bo_get_syncpoint(struct nouveau_bo *bo, unsigned int *out_threshold)
{
CALLED();
struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
return 0;
}
int
nouveau_bo_wait(struct nouveau_bo *bo, uint32_t access,
struct nouveau_client *client)
{
CALLED();
struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
struct nouveau_pushbuf *push;
int ret = 0;
return ret;
}
int
nouveau_bo_map(struct nouveau_bo *bo, uint32_t access,
struct nouveau_client *client)
{
CALLED();
struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
bo->map = nvbo->map_addr;
return nouveau_bo_wait(bo, access, client);
}
void
nouveau_bo_unmap(struct nouveau_bo *bo)
{
CALLED();
bo->map = NULL;
}
struct nouveau_screen;
bool nouveau_drm_screen_unref(struct nouveau_screen *screen)
{
return true;
}

View File

@ -1,86 +0,0 @@
#ifndef __NOUVEAU_LIBDRM_PRIVATE_H__
#define __NOUVEAU_LIBDRM_PRIVATE_H__
#include "libdrm_atomics.h"
#include "nouveau_drm.h"
#include "nouveau.h"
#include <switch.h>
#define BO_MAP_NUM_BUCKETS 31
struct nouveau_client_bo_map_entry {
struct nouveau_client_bo_map_entry *next;
struct nouveau_client_bo_map_entry **prev_next;
struct drm_nouveau_gem_pushbuf_bo *kref;
struct nouveau_pushbuf *push;
uint32_t bo_handle;
};
struct nouveau_client_bo_map {
struct nouveau_client_bo_map_entry *buckets[BO_MAP_NUM_BUCKETS+1];
};
struct nouveau_client_priv {
struct nouveau_client base;
struct nouveau_client_bo_map bomap;
};
static inline struct nouveau_client_priv *
nouveau_client(struct nouveau_client *client)
{
return (struct nouveau_client_priv *)client;
}
void
cli_map_free(struct nouveau_client *);
struct drm_nouveau_gem_pushbuf_bo *
cli_kref_get(struct nouveau_client *, struct nouveau_bo *bo);
struct nouveau_pushbuf *
cli_push_get(struct nouveau_client *, struct nouveau_bo *bo);
void
cli_kref_set(struct nouveau_client *, struct nouveau_bo *bo,
struct drm_nouveau_gem_pushbuf_bo *kref,
struct nouveau_pushbuf *push);
struct nouveau_bo_priv {
struct nouveau_bo base;
struct nouveau_list head;
atomic_t refcnt;
void* map_addr;
uint32_t name;
uint32_t access;
NvBuffer buffer;
NvFence fence;
};
static inline struct nouveau_bo_priv *
nouveau_bo(struct nouveau_bo *bo)
{
return (struct nouveau_bo_priv *)bo;
}
struct nouveau_device_priv {
struct nouveau_device base;
int close;
struct nouveau_list bo_list;
uint32_t *client;
int nr_client;
bool have_bo_usage;
int gart_limit_percent, vram_limit_percent;
uint64_t allocspace_offset;
Mutex lock;
NvGpu gpu;
};
static inline struct nouveau_device_priv *
nouveau_device(struct nouveau_device *dev)
{
return (struct nouveau_device_priv *)dev;
}
#endif

View File

@ -1,457 +0,0 @@
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include "libdrm_lists.h"
#include "nouveau_drm.h"
#include "nouveau.h"
#include "private.h"
#ifdef DEBUG
# define TRACE(x...) printf("nouveau: " x)
# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
#else
# define TRACE(x...)
# define CALLED()
#endif
struct nouveau_pushbuf_krec {
struct nouveau_pushbuf_krec *next;
struct drm_nouveau_gem_pushbuf_bo buffer[NOUVEAU_GEM_MAX_BUFFERS];
struct drm_nouveau_gem_pushbuf_push push[NOUVEAU_GEM_MAX_PUSH];
int nr_buffer;
int nr_push;
};
struct nouveau_pushbuf_priv {
struct nouveau_pushbuf base;
struct nouveau_pushbuf_krec *list;
struct nouveau_pushbuf_krec *krec;
struct nouveau_list bctx_list;
struct nouveau_bo *bo;
//NvBuffer fence_buf;
//u32 fence_num_cmds;
uint32_t type;
uint32_t *ptr;
uint32_t *bgn;
int bo_next;
int bo_nr;
struct nouveau_bo *bos[];
};
static inline struct nouveau_pushbuf_priv *
nouveau_pushbuf(struct nouveau_pushbuf *push)
{
return (struct nouveau_pushbuf_priv *)push;
}
static int pushbuf_validate(struct nouveau_pushbuf *, bool);
static int pushbuf_flush(struct nouveau_pushbuf *);
static bool
pushbuf_kref_fits(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
uint32_t *domains)
{
CALLED();
// Note: We assume we always have enough memory for the bo.
return true;
}
static struct drm_nouveau_gem_pushbuf_bo *
pushbuf_kref(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
uint32_t flags)
{
CALLED();
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
struct nouveau_pushbuf_krec *krec = nvpb->krec;
struct nouveau_pushbuf *fpush;
struct drm_nouveau_gem_pushbuf_bo *kref;
uint32_t domains, domains_wr, domains_rd;
domains = NOUVEAU_GEM_DOMAIN_GART;
domains_wr = domains * !!(flags & NOUVEAU_BO_WR);
domains_rd = domains * !!(flags & NOUVEAU_BO_RD);
/* if buffer is referenced on another pushbuf that is owned by the
* same client, we need to flush the other pushbuf first to ensure
* the correct ordering of commands
*/
fpush = cli_push_get(push->client, bo);
if (fpush && fpush != push)
pushbuf_flush(fpush);
kref = cli_kref_get(push->client, bo);
if (kref) {
kref->write_domains |= domains_wr;
kref->read_domains |= domains_rd;
} else {
if (krec->nr_buffer == NOUVEAU_GEM_MAX_BUFFERS ||
!pushbuf_kref_fits(push, bo, &domains))
return NULL;
kref = &krec->buffer[krec->nr_buffer++];
kref->bo = bo;
kref->handle = bo->handle;
kref->write_domains = domains_wr;
kref->read_domains = domains_rd;
cli_kref_set(push->client, bo, kref, push);
atomic_inc(&nouveau_bo(bo)->refcnt);
}
return kref;
}
#if 0
static uint32_t
pushbuf_krel(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
uint32_t data, uint32_t flags, uint32_t vor, uint32_t tor)
{
CALLED();
// Unneeded
return 0;
}
#endif
static void
pushbuf_dump(struct nouveau_pushbuf_krec *krec, int krec_id, int chid)
{
struct drm_nouveau_gem_pushbuf_push *kpsh;
struct drm_nouveau_gem_pushbuf_bo *kref;
struct nouveau_bo *bo;
uint32_t *bgn, *end;
int i;
TRACE("ch%d: krec %d pushes %d bufs %d\n", chid,
krec_id, krec->nr_push, krec->nr_buffer);
kref = krec->buffer;
for (i = 0; i < krec->nr_buffer; i++, kref++) {
TRACE("ch%d: buf %08x %08x %08x %08x\n", chid, i,
kref->handle, kref->read_domains, kref->write_domains);
}
kpsh = krec->push;
for (i = 0; i < krec->nr_push; i++, kpsh++) {
kref = krec->buffer + kpsh->bo_index;
bo = kref->bo;
bgn = (uint32_t *)((char *)bo->map + kpsh->offset);
end = bgn + (kpsh->length /4);
TRACE("ch%d: psh %08x %010llx %010llx\n", chid, kpsh->bo_index,
(unsigned long long)kpsh->offset,
(unsigned long long)(kpsh->offset + kpsh->length));
while (bgn < end)
TRACE("\t0x%08x\n", *bgn++);
}
}
static int
pushbuf_submit(struct nouveau_pushbuf *push, struct nouveau_object *chan)
{
CALLED();
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
struct nouveau_pushbuf_krec *krec = nvpb->list;
struct nouveau_device *dev = push->client->device;
struct nouveau_device_priv *nvdev = nouveau_device(dev);
struct drm_nouveau_gem_pushbuf_bo *kref;
struct drm_nouveau_gem_pushbuf_push *kpsh;
struct nouveau_fifo *fifo = chan->data;
struct nouveau_bo *bo;
struct nouveau_bo_priv *nvbo;
int krec_id = 0;
int ret = 0, i;
return ret;
}
static int
pushbuf_flush(struct nouveau_pushbuf *push)
{
CALLED();
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
struct nouveau_pushbuf_krec *krec = nvpb->krec;
struct drm_nouveau_gem_pushbuf_bo *kref;
struct nouveau_bufctx *bctx, *btmp;
struct nouveau_bo *bo;
int ret = 0, i;
return ret;
}
static void
pushbuf_refn_fail(struct nouveau_pushbuf *push, int sref)
{
CALLED();
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
struct nouveau_pushbuf_krec *krec = nvpb->krec;
struct drm_nouveau_gem_pushbuf_bo *kref;
kref = krec->buffer + sref;
while (krec->nr_buffer-- > sref) {
struct nouveau_bo *bo = kref->bo;
cli_kref_set(push->client, bo, NULL, NULL);
nouveau_bo_ref(NULL, &bo);
kref++;
}
krec->nr_buffer = sref;
}
static int
pushbuf_refn(struct nouveau_pushbuf *push, bool retry,
struct nouveau_pushbuf_refn *refs, int nr)
{
CALLED();
return 0;
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
struct nouveau_pushbuf_krec *krec = nvpb->krec;
struct drm_nouveau_gem_pushbuf_bo *kref;
int sref = krec->nr_buffer;
int ret = 0, i;
for (i = 0; i < nr; i++) {
kref = pushbuf_kref(push, refs[i].bo, refs[i].flags);
if (!kref) {
ret = -ENOSPC;
break;
}
}
if (ret) {
pushbuf_refn_fail(push, sref);
if (retry) {
pushbuf_flush(push);
nouveau_pushbuf_space(push, 0, 0, 0);
return pushbuf_refn(push, false, refs, nr);
}
}
return ret;
}
static int
pushbuf_validate(struct nouveau_pushbuf *push, bool retry)
{
CALLED();
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
struct nouveau_pushbuf_krec *krec = nvpb->krec;
struct drm_nouveau_gem_pushbuf_bo *kref;
struct nouveau_bufctx *bctx = push->bufctx;
struct nouveau_bufref *bref;
int relocs = bctx ? bctx->relocs * 2: 0;
int sref, ret;
ret = nouveau_pushbuf_space(push, relocs, relocs, 0);
if (ret || bctx == NULL)
return ret;
sref = krec->nr_buffer;
DRMLISTDEL(&bctx->head);
DRMLISTADD(&bctx->head, &nvpb->bctx_list);
DRMLISTFOREACHENTRY(bref, &bctx->pending, thead) {
kref = pushbuf_kref(push, bref->bo, bref->flags);
if (!kref) {
ret = -ENOSPC;
break;
}
}
DRMLISTJOIN(&bctx->pending, &bctx->current);
DRMINITLISTHEAD(&bctx->pending);
if (ret) {
pushbuf_refn_fail(push, sref);
if (retry) {
pushbuf_flush(push);
return pushbuf_validate(push, false);
}
}
return ret;
}
typedef uint32_t u32;
static u32
generate_fence_cmdlist(u32* fence_buf, u32 syncpt_id)
{
u32* cmd = fence_buf;
*cmd++ = 0x451 | (0 << 13) | (0 << 16) | (4 << 29);
*cmd++ = 0x0B2 | (0 << 13) | (1 << 16) | (1 << 29);
*cmd++ = syncpt_id | (1 << 20);
*cmd++ = 0x451 | (0 << 13) | (0 << 16) | (4 << 29);
*cmd++ = 0x3E0 | (0 << 13) | (0 << 16) | (4 << 29);
return cmd - fence_buf;
}
int
nouveau_pushbuf_new(struct nouveau_client *client, struct nouveau_object *chan,
int nr, uint32_t size, bool immediate,
struct nouveau_pushbuf **ppush)
{
CALLED();
struct nouveau_device_priv *nvdev = nouveau_device(client->device);
struct nouveau_pushbuf_priv *nvpb;
struct nouveau_pushbuf *push;
int ret;
nvpb = calloc(1, sizeof(*nvpb) + nr * sizeof(*nvpb->bos));
push = &nvpb->base;
push->client = client;
push->channel = immediate ? chan : NULL;
push->flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART | NOUVEAU_BO_MAP;
nvpb->type = NOUVEAU_BO_GART;
*ppush = push;
return 0;
}
void
nouveau_pushbuf_del(struct nouveau_pushbuf **ppush)
{
CALLED();
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(*ppush);
free(nvpb);
}
struct nouveau_bufctx *
nouveau_pushbuf_bufctx(struct nouveau_pushbuf *push, struct nouveau_bufctx *ctx)
{
CALLED();
struct nouveau_bufctx *prev = push->bufctx;
push->bufctx = ctx;
return prev;
}
int
nouveau_pushbuf_space(struct nouveau_pushbuf *push,
uint32_t dwords, uint32_t relocs, uint32_t pushes)
{
CALLED();
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
struct nouveau_pushbuf_krec *krec = nvpb->krec;
struct nouveau_client *client = push->client;
struct nouveau_bo *bo = NULL;
bool flushed = false;
int ret = 0;
return 0;
}
void
nouveau_pushbuf_data(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
uint64_t offset, uint64_t length)
{
CALLED();
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
struct nouveau_pushbuf_krec *krec = nvpb->krec;
struct drm_nouveau_gem_pushbuf_push *kpsh;
struct drm_nouveau_gem_pushbuf_bo *kref;
if (bo != nvpb->bo && nvpb->bgn != push->cur) {
nouveau_pushbuf_data(push, nvpb->bo,
(nvpb->bgn - nvpb->ptr) * 4,
(push->cur - nvpb->bgn) * 4);
nvpb->bgn = push->cur;
}
if (bo) {
kref = cli_kref_get(push->client, bo);
assert(kref);
kpsh = &krec->push[krec->nr_push++];
kpsh->bo_index = kref - krec->buffer;
kpsh->offset = offset;
kpsh->length = length;
}
}
int
nouveau_pushbuf_refn(struct nouveau_pushbuf *push,
struct nouveau_pushbuf_refn *refs, int nr)
{
CALLED();
return pushbuf_refn(push, true, refs, nr);
}
void
nouveau_pushbuf_reloc(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
uint32_t data, uint32_t flags, uint32_t vor, uint32_t tor)
{
CALLED();
// Unimplemented
}
int
nouveau_pushbuf_validate(struct nouveau_pushbuf *push)
{
CALLED();
return 0;
}
uint32_t
nouveau_pushbuf_refd(struct nouveau_pushbuf *push, struct nouveau_bo *bo)
{
CALLED();
struct drm_nouveau_gem_pushbuf_bo *kref;
uint32_t flags = 0;
if (cli_push_get(push->client, bo) == push) {
kref = cli_kref_get(push->client, bo);
assert(kref);
if (kref->read_domains)
flags |= NOUVEAU_BO_RD;
if (kref->write_domains)
flags |= NOUVEAU_BO_WR;
}
return flags;
}
int
nouveau_pushbuf_kick(struct nouveau_pushbuf *push, struct nouveau_object *chan)
{
CALLED();
if (!push->channel)
return pushbuf_submit(push, chan);
pushbuf_flush(push);
return pushbuf_validate(push, false);
}

View File

@ -1,590 +0,0 @@
#include "boo/graphicsdev/nx_compiler.hpp"
/*
* Copyright © 2008, 2009 Intel Corporation
* Boo Modifications © 2018 Jack Andersen
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/** @file nx_compiler.cpp
*
* Based on standalone.cpp in compiler/glsl. This file provides a means to
* compile and link GLSL sources directly into driver programs for the
* Nouveau GM107 chipset configuration.
*/
#include "ast.h"
#include "glsl_parser_extras.h"
#include "ir_optimization.h"
#include "program.h"
#include "loop_analysis.h"
#include "string_to_uint_map.h"
#include "util/set.h"
#include "linker.h"
#include "ir_builder_print_visitor.h"
#include "builtin_functions.h"
#include "opt_add_neg_to_sub.h"
#include "main/shaderobj.h"
#include "st_program.h"
extern "C" {
#include "nouveau_winsys.h"
#include "nouveau_screen.h"
#include "nvc0/nvc0_program.h"
}
_GLAPI_EXPORT __thread void* _glapi_tls_Context;
_GLAPI_EXPORT __thread struct _glapi_table* _glapi_tls_Dispatch;
int _glapi_add_dispatch(const char* const* function_names, const char* parameter_signature) { return 0; }
void _glapi_destroy_multithread(void) {}
void _glapi_check_multithread(void) {}
void _glapi_set_context(void* context) { _glapi_tls_Context = context; }
void* _glapi_get_context() { return _glapi_tls_Context; }
void _glapi_set_dispatch(struct _glapi_table* dispatch) { _glapi_tls_Dispatch = dispatch; }
struct _glapi_table* _glapi_get_dispatch() {
return _glapi_tls_Dispatch;
}
GLuint _glapi_get_dispatch_table_size(void) {
/*
* The dispatch table size (number of entries) is the size of the
* _glapi_table struct plus the number of dynamic entries we can add.
* The extra slots can be filled in by DRI drivers that register new
* extension functions.
*/
return 0;
}
class dead_variable_visitor : public ir_hierarchical_visitor {
public:
dead_variable_visitor() { variables = _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); }
virtual ~dead_variable_visitor() { _mesa_set_destroy(variables, NULL); }
virtual ir_visitor_status visit(ir_variable* ir) {
/* If the variable is auto or temp, add it to the set of variables that
* are candidates for removal.
*/
if (ir->data.mode != ir_var_auto && ir->data.mode != ir_var_temporary)
return visit_continue;
_mesa_set_add(variables, ir);
return visit_continue;
}
virtual ir_visitor_status visit(ir_dereference_variable* ir) {
struct set_entry* entry = _mesa_set_search(variables, ir->var);
/* If a variable is dereferenced at all, remove it from the set of
* variables that are candidates for removal.
*/
if (entry != NULL)
_mesa_set_remove(variables, entry);
return visit_continue;
}
void remove_dead_variables() {
struct set_entry* entry;
set_foreach(variables, entry) {
ir_variable* ir = (ir_variable*)entry->key;
assert(ir->ir_type == ir_type_variable);
ir->remove();
}
}
private:
set* variables;
};
void nx_compiler::compile_shader(struct gl_context* ctx, struct gl_shader* shader) {
struct _mesa_glsl_parse_state* state = new (shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
_mesa_glsl_compile_shader(ctx, shader, m_options.dump_ast, m_options.dump_hir, true);
/* Print out the resulting IR */
if (!state->error && m_options.dump_lir) {
_mesa_print_ir(stdout, shader->ir, state);
}
}
nx_compiler::nx_compiler() {
m_options.glsl_version = 330;
m_options.do_link = true;
}
nx_compiler::~nx_compiler() {
if (m_ownsCtx) {
_mesa_glsl_release_types();
_mesa_glsl_release_builtin_functions();
if (m_st)
st_destroy_context(m_st);
if (m_screen)
m_screen->destroy(m_screen);
}
}
bool nx_compiler::initialize(struct pipe_screen* screen, struct st_context* st, const struct standalone_options* o) {
m_screen = screen;
m_st = st;
if (o)
memcpy(&m_options, o, sizeof(*o));
return true;
}
bool nx_compiler::initialize(const struct standalone_options* o) {
m_ownsCtx = true;
bool glsl_es;
if (o)
memcpy(&m_options, o, sizeof(*o));
switch (m_options.glsl_version) {
case 100:
case 300:
glsl_es = true;
break;
case 110:
case 120:
case 130:
case 140:
case 150:
case 330:
case 400:
case 410:
case 420:
case 430:
case 440:
case 450:
case 460:
glsl_es = false;
break;
default:
fprintf(stderr, "Unrecognized GLSL version `%d'\n", m_options.glsl_version);
return false;
}
gl_api use_api;
if (glsl_es) {
use_api = API_OPENGLES2;
} else {
use_api = m_options.glsl_version > 130 ? API_OPENGL_CORE : API_OPENGL_COMPAT;
}
struct nouveau_screen* (*init)(struct nouveau_device*);
struct nouveau_drm* fakedrm = (struct nouveau_drm*)malloc(sizeof(struct nouveau_drm));
if (!fakedrm)
return false;
memset(fakedrm, 0, sizeof(*fakedrm));
nouveau_device* ndev;
if (nouveau_device_new(&fakedrm->client, 0, nullptr, 0, &ndev))
return false;
switch (ndev->chipset & ~0xf) {
#if 0
case 0x30:
case 0x40:
case 0x60:
init = nv30_screen_create;
break;
case 0x50:
case 0x80:
case 0x90:
case 0xa0:
init = nv50_screen_create;
break;
#endif
default:
case 0xc0:
case 0xd0:
case 0xe0:
case 0xf0:
case 0x100:
case 0x110:
case 0x120:
case 0x130:
init = nvc0_screen_create;
break;
}
struct nouveau_screen* screen = init(ndev);
if (!screen)
return false;
screen->refcount = 1;
struct pipe_context* p_ctx = screen->base.context_create(&screen->base, nullptr, 0);
if (!p_ctx) {
screen->base.destroy(&screen->base);
return false;
}
st_config_options opts = {};
struct st_context* st = st_create_context(use_api, p_ctx, nullptr, nullptr, &opts, false);
if (!st) {
screen->base.destroy(&screen->base);
return false;
}
return initialize(&screen->base, st);
}
nx_shader_stage_object::nx_shader_stage_object(const nx_shader_stage_object& other) : m_parent(other.m_parent) {
if (!other.m_shader || !m_parent)
return;
struct gl_context* ctx = m_parent->m_st->ctx;
_mesa_reference_shader(ctx, &m_shader, other.m_shader);
}
nx_shader_stage_object& nx_shader_stage_object::operator=(const nx_shader_stage_object& other) {
m_parent = other.m_parent;
if (!other.m_shader || !m_parent)
return *this;
struct gl_context* ctx = m_parent->m_st->ctx;
_mesa_reference_shader(ctx, &m_shader, other.m_shader);
return *this;
}
void nx_shader_stage_object::reset() {
if (!m_shader || !m_parent)
return;
struct gl_context* ctx = m_parent->m_st->ctx;
_mesa_reference_shader(ctx, &m_shader, nullptr);
}
nx_shader_stage_object::operator bool() const {
if (!m_shader)
return false;
return m_shader->CompileStatus;
}
nx_shader_stage nx_shader_stage_object::stage() const { return nx_shader_stage(m_shader->Stage); }
const char* nx_shader_stage_object::info_log() const {
if (!m_shader)
return nullptr;
return m_shader->InfoLog;
}
nx_linked_shader::nx_linked_shader(const nx_linked_shader& other) : m_parent(other.m_parent) {
if (!other.m_program || !m_parent)
return;
struct gl_context* ctx = m_parent->m_st->ctx;
_mesa_reference_shader_program(ctx, &m_program, other.m_program);
}
nx_linked_shader& nx_linked_shader::operator=(const nx_linked_shader& other) {
m_parent = other.m_parent;
if (!other.m_program || !m_parent)
return *this;
struct gl_context* ctx = m_parent->m_st->ctx;
_mesa_reference_shader_program(ctx, &m_program, other.m_program);
return *this;
}
void nx_linked_shader::reset() {
if (!m_program || !m_parent)
return;
struct gl_context* ctx = m_parent->m_st->ctx;
_mesa_reference_shader_program(ctx, &m_program, nullptr);
}
nx_shader_stage_object nx_compiler::compile(nx_shader_stage type, const char* source) {
struct gl_context* ctx = m_st->ctx;
nx_shader_stage_object ret(*this);
ret.m_shader = rzalloc(nullptr, gl_shader);
assert(ret.m_shader != NULL);
ret.m_shader->RefCount = 1;
ret.m_shader->Stage = gl_shader_stage(type);
ret.m_shader->Source = source;
compile_shader(ctx, ret.m_shader);
/* Mesa doesn't actually own the source, so take it away here */
ret.m_shader->Source = nullptr;
return ret;
}
nx_linked_shader nx_compiler::link(unsigned num_stages, const nx_shader_stage_object** stages, std::string* infoLog) {
nx_linked_shader ret(*this);
int status = EXIT_SUCCESS;
struct gl_context* ctx = m_st->ctx;
struct gl_shader_program* whole_program;
whole_program = rzalloc(NULL, struct gl_shader_program);
assert(whole_program != NULL);
whole_program->Type = GL_SHADER_PROGRAM_MESA;
whole_program->data = rzalloc(whole_program, struct gl_shader_program_data);
assert(whole_program->data != NULL);
whole_program->data->RefCount = 1;
whole_program->data->InfoLog = ralloc_strdup(whole_program->data, "");
ret.m_program = whole_program;
whole_program->Shaders = (struct gl_shader**)calloc(num_stages, sizeof(struct gl_shader*));
assert(whole_program->Shaders != NULL);
for (unsigned i = 0; i < num_stages; i++) {
whole_program->Shaders[whole_program->NumShaders] = stages[i]->m_shader;
stages[i]->m_shader->RefCount++;
whole_program->NumShaders++;
if (!stages[i]->m_shader->CompileStatus) {
status = EXIT_FAILURE;
break;
}
}
if (status == EXIT_SUCCESS) {
_mesa_clear_shader_program_data(ctx, whole_program);
if (m_options.do_link) {
link_shaders(ctx, whole_program);
for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
if (whole_program->_LinkedShaders[i])
whole_program->_LinkedShaders[i]->Program->Target = _mesa_shader_stage_to_program(i);
}
} else {
const gl_shader_stage stage = whole_program->Shaders[0]->Stage;
whole_program->data->LinkStatus = LINKING_SUCCESS;
whole_program->_LinkedShaders[stage] =
link_intrastage_shaders(whole_program /* mem_ctx */, ctx, whole_program, whole_program->Shaders, 1, true);
whole_program->_LinkedShaders[stage]->Program->Target = _mesa_shader_stage_to_program(stage);
/* Par-linking can fail, for example, if there are undefined external
* references.
*/
if (whole_program->_LinkedShaders[stage] != NULL) {
assert(whole_program->data->LinkStatus);
struct gl_shader_compiler_options* const compiler_options = &ctx->Const.ShaderCompilerOptions[stage];
exec_list* const ir = whole_program->_LinkedShaders[stage]->ir;
bool progress;
do {
progress = do_function_inlining(ir);
progress = do_common_optimization(ir, false, false, compiler_options, true) && progress;
} while (progress);
}
}
status = (whole_program->data->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
if (infoLog)
*infoLog = whole_program->data->InfoLog;
if (status == EXIT_SUCCESS) {
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_linked_shader* shader = whole_program->_LinkedShaders[i];
if (!shader)
continue;
add_neg_to_sub_visitor v;
visit_list_elements(&v, shader->ir);
dead_variable_visitor dv;
visit_list_elements(&dv, shader->ir);
dv.remove_dead_variables();
}
if (m_options.dump_builder) {
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_linked_shader* shader = whole_program->_LinkedShaders[i];
if (!shader)
continue;
_mesa_print_builder_for_ir(stdout, shader->ir);
}
}
ctx->_Shader = &ctx->Shader;
st_link_shader(ctx, whole_program);
ctx->_Shader = nullptr;
return ret;
}
}
return nx_linked_shader(*this);
}
static void SizeProgramBuffer(const nvc0_program* prog, size_t& sz) {
sz += 140;
sz += prog->code_size;
}
template <class T>
static void OutputField(T f, uint8_t*& ptr) {
memcpy(ptr, &f, sizeof(f));
ptr += sizeof(f);
}
static void BuildProgramBuffer(const nvc0_program* prog, uint8_t*& ptr) {
OutputField(prog->type, ptr);
OutputField(prog->translated, ptr);
OutputField(prog->need_tls, ptr);
OutputField(prog->num_gprs, ptr);
OutputField<uint32_t>(prog->code_base, ptr);
OutputField<uint32_t>(prog->code_size, ptr);
OutputField<uint32_t>(prog->parm_size, ptr);
for (const auto& h : prog->hdr)
OutputField(h, ptr);
for (const auto& h : prog->flags)
OutputField(h, ptr);
OutputField(prog->vp.clip_mode, ptr);
OutputField(prog->vp.clip_enable, ptr);
OutputField(prog->vp.cull_enable, ptr);
OutputField(prog->vp.num_ucps, ptr);
OutputField(prog->vp.edgeflag, ptr);
OutputField(prog->vp.need_vertex_id, ptr);
OutputField(prog->vp.need_draw_parameters, ptr);
OutputField(prog->fp.early_z, ptr);
OutputField(prog->fp.colors, ptr);
OutputField(prog->fp.color_interp[0], ptr);
OutputField(prog->fp.color_interp[1], ptr);
OutputField(prog->fp.sample_mask_in, ptr);
OutputField(prog->fp.force_persample_interp, ptr);
OutputField(prog->fp.flatshade, ptr);
OutputField(prog->fp.reads_framebuffer, ptr);
OutputField(prog->fp.post_depth_coverage, ptr);
OutputField(prog->tp.tess_mode, ptr);
OutputField(prog->tp.input_patch_size, ptr);
OutputField(prog->cp.lmem_size, ptr);
OutputField(prog->cp.smem_size, ptr);
OutputField(prog->num_barriers, ptr);
memcpy(ptr, prog->code, prog->code_size);
ptr += prog->code_size;
}
std::pair<std::shared_ptr<uint8_t[]>, size_t> nx_compiler::offline_link(unsigned num_stages,
const nx_shader_stage_object** stages,
std::string* infoLog) {
std::pair<std::shared_ptr<uint8_t[]>, size_t> ret = {};
auto whole_program = link(num_stages, stages, infoLog);
if (!whole_program)
return ret;
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_linked_shader* shader = whole_program.m_program->_LinkedShaders[i];
if (!shader)
continue;
struct gl_program* prog = shader->Program;
switch (prog->Target) {
case GL_VERTEX_PROGRAM_ARB: {
struct st_vertex_program* p = (struct st_vertex_program*)prog;
nvc0_program* dp = (nvc0_program*)p->variants->driver_shader;
SizeProgramBuffer(dp, ret.second);
break;
}
case GL_TESS_CONTROL_PROGRAM_NV: {
struct st_common_program* p = st_common_program(prog);
nvc0_program* dp = (nvc0_program*)p->variants->driver_shader;
SizeProgramBuffer(dp, ret.second);
break;
}
case GL_TESS_EVALUATION_PROGRAM_NV: {
struct st_common_program* p = st_common_program(prog);
nvc0_program* dp = (nvc0_program*)p->variants->driver_shader;
SizeProgramBuffer(dp, ret.second);
break;
}
case GL_GEOMETRY_PROGRAM_NV: {
struct st_common_program* p = st_common_program(prog);
nvc0_program* dp = (nvc0_program*)p->variants->driver_shader;
SizeProgramBuffer(dp, ret.second);
break;
}
case GL_FRAGMENT_PROGRAM_ARB: {
struct st_fragment_program* p = (struct st_fragment_program*)prog;
nvc0_program* dp = (nvc0_program*)p->variants->driver_shader;
SizeProgramBuffer(dp, ret.second);
break;
}
default:
assert(0);
}
}
ret.first.reset(new uint8_t[ret.second]);
uint8_t* pbuf = ret.first.get();
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_linked_shader* shader = whole_program.m_program->_LinkedShaders[i];
if (!shader)
continue;
struct gl_program* prog = shader->Program;
switch (prog->Target) {
case GL_VERTEX_PROGRAM_ARB: {
struct st_vertex_program* p = (struct st_vertex_program*)prog;
nvc0_program* dp = (nvc0_program*)p->variants->driver_shader;
BuildProgramBuffer(dp, pbuf);
break;
}
case GL_TESS_CONTROL_PROGRAM_NV: {
struct st_common_program* p = st_common_program(prog);
nvc0_program* dp = (nvc0_program*)p->variants->driver_shader;
BuildProgramBuffer(dp, pbuf);
break;
}
case GL_TESS_EVALUATION_PROGRAM_NV: {
struct st_common_program* p = st_common_program(prog);
nvc0_program* dp = (nvc0_program*)p->variants->driver_shader;
BuildProgramBuffer(dp, pbuf);
break;
}
case GL_GEOMETRY_PROGRAM_NV: {
struct st_common_program* p = st_common_program(prog);
nvc0_program* dp = (nvc0_program*)p->variants->driver_shader;
BuildProgramBuffer(dp, pbuf);
break;
}
case GL_FRAGMENT_PROGRAM_ARB: {
struct st_fragment_program* p = (struct st_fragment_program*)prog;
nvc0_program* dp = (nvc0_program*)p->variants->driver_shader;
BuildProgramBuffer(dp, pbuf);
break;
}
default:
assert(0);
}
}
return ret;
}

View File

@ -1,36 +0,0 @@
#include "boo/graphicsdev/nx_compiler.hpp"
int main(int argc, char** argv) {
nx_compiler c;
c.initialize();
nx_shader_stage_object objs[] = {c.compile(nx_shader_stage::VERTEX,
"#version 330\n"
"#extension GL_ARB_separate_shader_objects: enable\n"
"#extension GL_ARB_shading_language_420pack: enable\n"
"layout(location=0) in vec3 in_pos;\n"
"layout(location=1) in vec3 in_norm;\n"
"layout(location=2) in vec2 in_uv;\n"
"layout(location=0) out vec2 out_uv;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(in_pos, 1.0).zyxx;\n"
" out_uv = in_uv;\n"
"}"),
c.compile(nx_shader_stage::FRAGMENT,
"#version 330\n"
"#extension GL_ARB_separate_shader_objects: enable\n"
"#extension GL_ARB_shading_language_420pack: enable\n"
"layout(binding=8) uniform sampler2D texs[2];\n"
"layout(location=0) out vec4 out_frag;\n"
"layout(location=0) in vec2 out_uv;\n"
"void main()\n"
"{\n"
" out_frag = texture(texs[0], out_uv) + texture(texs[1], out_uv);\n"
"}")};
std::string log;
auto linkData = c.link(2, objs, &log);
return 0;
}

View File

@ -1,25 +0,0 @@
[binaries]
c = '@CMAKE_C_COMPILER@'
cpp = '@CMAKE_CXX_COMPILER@'
ar = '@CMAKE_AR@'
strip = '@CMAKE_STRIP@'
[properties]
sizeof_int = 4
sizeof_wchar_t = 4
sizeof_void* = 8
alignment_char = 1
alignment_void* = 8
alignment_double = 8
c_args = ['-march=armv8-a', '-mtune=cortex-a57', '-mtp=soft', '-fPIC', '-D__SWITCH__', '-I@DEVKITPRO@/libnx/include',
'-I@LIBDRM_DIR@/include', '-DDEBUG=1', '-DHAVE_LIBDRM', '-D_GNU_SOURCE']
cpp_args = ['-march=armv8-a', '-mtune=cortex-a57', '-mtp=soft', '-fPIC', '-D__SWITCH__', '-I@DEVKITPRO@/libnx/include',
'-I@LIBDRM_DIR@/include', '-DDEBUG=1', '-DHAVE_LIBDRM', '-D_GNU_SOURCE']
[host_machine]
system = 'switch'
cpu_family = 'armv8-a'
cpu = 'cortex-a57'
endian = 'little'

View File

@ -1,27 +0,0 @@
#include "lib/inputdev/IHIDDevice.hpp"
namespace boo {
class HIDDeviceNX : public IHIDDevice {
DeviceToken& m_token;
std::shared_ptr<DeviceBase> m_devImp;
std::string_view m_devPath;
public:
HIDDeviceNX(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
: m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {}
void _deviceDisconnected() override {}
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) override { return false; }
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) override { return 0; }
std::vector<uint8_t> _getReportDescriptor() override { return {}; }
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override { return false; }
size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override { return 0; }
void _startThread() override {}
};
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {
return std::make_shared<HIDDeviceNX>(token, devImp);
}
} // namespace boo

View File

@ -1,18 +0,0 @@
#include "boo/inputdev/IHIDListener.hpp"
namespace boo {
class HIDListenerNX : public IHIDListener {
DeviceFinder& m_finder;
public:
HIDListenerNX(DeviceFinder& finder) : m_finder(finder) {}
bool startScanning() override { return false; }
bool stopScanning() override { return false; }
bool scanNow() override { return false; }
};
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder) { return std::make_unique<HIDListenerNX>(finder); }
} // namespace boo

View File

@ -1,105 +0,0 @@
#include "nxstl/thread"
#include "nxstl/condition_variable"
#include "nxstl/mutex"
#include "boo/IApplication.hpp"
#include "boo/graphicsdev/NX.hpp"
#include <climits>
#include <logvisor/logvisor.hpp>
#include <switch.h>
namespace boo {
static logvisor::Module Log("boo::NXApplication");
std::shared_ptr<IWindow> _WindowNXNew(std::string_view title, NXContext* nxCtx);
class ApplicationNX : public IApplication {
IApplicationCallback& m_callback;
const std::string m_uniqueName;
const std::string m_friendlyName;
const std::string m_pname;
const std::vector<std::string> m_args;
NXContext m_nxCtx;
void _deletedWindow(IWindow* window) override {}
public:
ApplicationNX(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName,
std::string_view pname, const std::vector<std::string>& args, std::string_view gfxApi, uint32_t samples,
uint32_t anisotropy, bool deepColor, bool singleInstance)
: m_callback(callback), m_uniqueName(uniqueName), m_friendlyName(friendlyName), m_pname(pname), m_args(args) {}
EPlatformType getPlatformType() const override { return EPlatformType::NX; }
int run() override {
/* Spawn client thread */
int clientReturn = INT_MIN;
std::mutex initmt;
std::condition_variable initcv;
std::unique_lock<std::mutex> outerLk(initmt);
std::thread clientThread([&]() {
std::unique_lock<std::mutex> innerLk(initmt);
innerLk.unlock();
initcv.notify_one();
std::string thrName = std::string(getFriendlyName()) + " Client";
logvisor::RegisterThreadName(thrName.c_str());
clientReturn = m_callback.appMain(this);
});
initcv.wait(outerLk);
// Main graphics loop
while (clientReturn == INT_MIN && appletMainLoop()) {
// Get and process input
hidScanInput();
u32 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
if (kDown & KEY_PLUS)
break;
}
m_callback.appQuitting(this);
if (clientThread.joinable())
clientThread.join();
return 0;
}
std::string_view getUniqueName() const override { return m_uniqueName; }
std::string_view getFriendlyName() const override { return m_friendlyName; }
std::string_view getProcessName() const override { return m_pname; }
const std::vector<std::string>& getArgs() const override { return m_args; }
std::shared_ptr<IWindow> m_window;
std::shared_ptr<IWindow> newWindow(std::string_view title) override {
if (m_window)
Log.report(logvisor::Fatal, FMT_STRING("Only 1 window allowed on NX"));
m_window = _WindowNXNew(title, &m_nxCtx);
return m_window;
}
};
IApplication* APP = nullptr;
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, SystemStringView uniqueName,
SystemStringView friendlyName, SystemStringView pname, const std::vector<SystemString>& args,
std::string_view gfxApi, uint32_t samples, uint32_t anisotropy, bool deepColor,
bool singleInstance) {
std::string thrName = std::string(friendlyName) + " Main Thread";
logvisor::RegisterThreadName(thrName.c_str());
if (APP)
return 1;
APP = new ApplicationNX(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor,
singleInstance);
int ret = APP->run();
delete APP;
APP = nullptr;
return ret;
}
} // namespace boo

View File

@ -1,113 +0,0 @@
#include "boo/IWindow.hpp"
#include "boo/IGraphicsContext.hpp"
#include "boo/graphicsdev/NX.hpp"
#include <logvisor/logvisor.hpp>
#include <switch.h>
namespace boo {
std::unique_ptr<IGraphicsCommandQueue> _NewNXCommandQueue(NXContext* ctx, IGraphicsContext* parent);
std::unique_ptr<IGraphicsDataFactory> _NewNXDataFactory(IGraphicsContext* parent, NXContext* ctx);
struct GraphicsContextNX : IGraphicsContext {
NXContext* m_nxCtx;
std::unique_ptr<IGraphicsDataFactory> m_dataFactory;
std::unique_ptr<IGraphicsCommandQueue> m_commandQueue;
public:
explicit GraphicsContextNX(NXContext* nxCtx) : m_nxCtx(nxCtx) {
m_dataFactory = _NewNXDataFactory(this, nxCtx);
m_commandQueue = _NewNXCommandQueue(nxCtx, this);
}
EGraphicsAPI getAPI() const override { return EGraphicsAPI::NX; }
EPixelFormat getPixelFormat() const override { return EPixelFormat::RGBA8; }
void setPixelFormat(EPixelFormat pf) override {}
bool initializeContext(void* handle) override { return m_nxCtx->initialize(); }
void makeCurrent() override {}
void postInit() override {}
void present() override {}
IGraphicsCommandQueue* getCommandQueue() override { return m_commandQueue.get(); }
IGraphicsDataFactory* getDataFactory() override { return m_dataFactory.get(); }
IGraphicsDataFactory* getMainContextDataFactory() override { return m_dataFactory.get(); }
IGraphicsDataFactory* getLoadContextDataFactory() override { return m_dataFactory.get(); }
};
class WindowNX : public IWindow {
std::string m_title;
std::unique_ptr<GraphicsContextNX> m_gfxCtx;
IWindowCallback* m_callback = nullptr;
public:
WindowNX(std::string_view title, NXContext* nxCtx) : m_title(title), m_gfxCtx(new GraphicsContextNX(nxCtx)) {
m_gfxCtx->initializeContext(nullptr);
}
void setCallback(IWindowCallback* cb) override { m_callback = cb; }
void closeWindow() override {}
void showWindow() override {}
void hideWindow() override {}
SystemString getTitle() override { return m_title; }
void setTitle(SystemStringView title) override { m_title = title; }
void setCursor(EMouseCursor cursor) override {}
void setWaitCursor(bool wait) override {}
void setWindowFrameDefault() override {}
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const override {
u32 width, height;
gfxGetFramebufferResolution(&width, &height);
xOut = 0;
yOut = 0;
wOut = width;
hOut = height;
}
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const override {
u32 width, height;
gfxGetFramebufferResolution(&width, &height);
xOut = 0;
yOut = 0;
wOut = width;
hOut = height;
}
void setWindowFrame(float x, float y, float w, float h) override {}
void setWindowFrame(int x, int y, int w, int h) override {}
float getVirtualPixelFactor() const override { return 1.f; }
bool isFullscreen() const override { return true; }
void setFullscreen(bool fs) override {}
void claimKeyboardFocus(const int coord[2]) override {}
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) override { return false; }
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) override { return {}; }
void waitForRetrace() override {}
uintptr_t getPlatformHandle() const override { return 0; }
bool _incomingEvent([[maybe_unused]] void* event) override { return false; }
void _cleanup() override {}
ETouchType getTouchType() const override { return ETouchType::Display; }
void setStyle(EWindowStyle style) override {}
EWindowStyle getStyle() const override { return EWindowStyle::None; }
void setTouchBarProvider(void*) override {}
IGraphicsCommandQueue* getCommandQueue() override { return m_gfxCtx->getCommandQueue(); }
IGraphicsDataFactory* getDataFactory() override { return m_gfxCtx->getDataFactory(); }
IGraphicsDataFactory* getMainContextDataFactory() override { return m_gfxCtx->getMainContextDataFactory(); }
IGraphicsDataFactory* getLoadContextDataFactory() override { return m_gfxCtx->getLoadContextDataFactory(); }
};
std::shared_ptr<IWindow> _WindowNXNew(std::string_view title, NXContext* nxCtx) {
std::shared_ptr<IWindow> ret = std::make_shared<WindowNX>(title, nxCtx);
return ret;
}
} // namespace boo

@ -1 +1 @@
Subproject commit bb113e03f8f714d8ca29242d1ff6ef68716fa465
Subproject commit 33e732259531980fc1f33523887360ea96070621