fatal: update screen task to use native window directly

This commit is contained in:
Michael Scire 2021-01-18 16:54:55 -08:00
parent ea9d360b14
commit 2696240566

View file

@ -48,28 +48,9 @@ namespace ams::fatal::srv {
}
extern "C" void *__libnx_tmem_alloc(size_t size) {
return ams::fatal::srv::g_nv_transfer_memory;
}
extern "C" void __libnx_tmem_free(void *mem) {
/* ... */
}
extern "C" void *__libnx_framebuffer_alloc(size_t size) {
return ams::fatal::srv::g_framebuffer_memory;
}
extern "C" void __libnx_framebuffer_free(void *mem) {
/* ... */
}
extern "C" void *__libnx_framebuffer_linear_alloc(size_t size) {
AMS_ABORT("__libnx_framebuffer_linear_alloc was called");
}
extern "C" void __libnx_framebuffer_linear_free(void *mem) {
AMS_ABORT("__libnx_framebuffer_linear_free was called");
extern "C" ::Result __nx_nv_create_tmem(TransferMemory *t, u32 *out_size, Permission perm) {
*out_size = sizeof(ams::fatal::srv::g_nv_transfer_memory);
return tmemCreateFromMemory(t, ams::fatal::srv::g_nv_transfer_memory, sizeof(ams::fatal::srv::g_nv_transfer_memory), perm);
}
namespace ams::fatal::srv {
@ -92,12 +73,14 @@ namespace ams::fatal::srv {
ViDisplay display;
ViLayer layer;
NWindow win;
Framebuffer fb;
NvMap map;
private:
Result SetupDisplayInternal();
Result SetupDisplayExternal();
Result PrepareScreenForDrawing();
void PreRenderFrameBuffer();
Result InitializeNativeWindow();
void DisplayPreRenderedFrame();
Result ShowFatal();
public:
virtual Result Run() override;
@ -192,15 +175,15 @@ namespace ams::fatal::srv {
/* Display a layer of 1280 x 720 at 1.5x magnification */
/* NOTE: N uses 2 (770x400) RGBA4444 buffers (tiled buffer + linear). */
/* We use a single 1280x720 tiled RGB565 buffer. */
constexpr s32 raw_width = FatalScreenWidth;
constexpr s32 raw_height = FatalScreenHeight;
constexpr s32 layer_width = ((raw_width) * 3) / 2;
constexpr s32 layer_height = ((raw_height) * 3) / 2;
constexpr s32 RawWidth = FatalScreenWidth;
constexpr s32 RawHeight = FatalScreenHeight;
constexpr s32 LayerWidth = ((RawWidth) * 3) / 2;
constexpr s32 LayerHeight = ((RawHeight) * 3) / 2;
const float layer_x = static_cast<float>((display_width - layer_width) / 2);
const float layer_y = static_cast<float>((display_height - layer_height) / 2);
const float layer_x = static_cast<float>((display_width - LayerWidth) / 2);
const float layer_y = static_cast<float>((display_height - LayerHeight) / 2);
R_TRY(viSetLayerSize(&this->layer, layer_width, layer_height));
R_TRY(viSetLayerSize(&this->layer, LayerWidth, LayerHeight));
/* Set the layer's Z at display maximum, to be above everything else .*/
R_TRY(viSetLayerZ(&this->layer, FatalLayerZ));
@ -210,7 +193,7 @@ namespace ams::fatal::srv {
/* Create framebuffer. */
R_TRY(nwindowCreateFromLayer(&this->win, &this->layer));
R_TRY(framebufferCreate(&this->fb, &this->win, raw_width, raw_height, PIXEL_FORMAT_RGB_565, 1));
R_TRY(this->InitializeNativeWindow());
}
return ResultSuccess();
@ -450,6 +433,52 @@ namespace ams::fatal::srv {
}
}
Result ShowFatalTask::InitializeNativeWindow() {
/* Setup nv driver. */
R_TRY(nvInitialize());
R_TRY(nvMapInit());
R_TRY(nvFenceInit());
/* Create nvmap. */
R_TRY(nvMapCreate(&this->map, g_framebuffer_memory, sizeof(g_framebuffer_memory), 0x20000, NvKind_Pitch, true));
/* Setup graphics buffer. */
{
NvGraphicBuffer grbuf = {};
grbuf.header.num_ints = (sizeof(NvGraphicBuffer) - sizeof(NativeHandle)) / 4;
grbuf.unk0 = -1;
grbuf.magic = 0xDAFFCAFF;
grbuf.pid = 42;
grbuf.usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
grbuf.format = PIXEL_FORMAT_RGB_565;
grbuf.ext_format = PIXEL_FORMAT_RGB_565;
grbuf.num_planes = 1;
grbuf.planes[0].width = FatalScreenWidth;
grbuf.planes[0].height = FatalScreenHeight;
grbuf.planes[0].color_format = NvColorFormat_R5G6B5;
grbuf.planes[0].layout = NvLayout_BlockLinear;
grbuf.planes[0].kind = NvKind_Generic_16BX2;
grbuf.planes[0].block_height_log2 = 4;
grbuf.nvmap_id = nvMapGetId(&this->map);
grbuf.stride = FatalScreenWidthAligned;
grbuf.total_size = sizeof(g_framebuffer_memory);
grbuf.planes[0].pitch = FatalScreenWidthAlignedBytes;
grbuf.planes[0].size = sizeof(g_framebuffer_memory);
grbuf.planes[0].offset = 0;
R_TRY(nwindowConfigureBuffer(&this->win, 0, &grbuf));
}
return ResultSuccess();
}
void ShowFatalTask::DisplayPreRenderedFrame() {
s32 slot;
R_ABORT_UNLESS(nwindowDequeueBuffer(&this->win, &slot, nullptr));
dd::FlushDataCache(g_framebuffer_memory, sizeof(g_framebuffer_memory));
R_ABORT_UNLESS(nwindowQueueBuffer(&this->win, this->win.cur_slot, NULL));
}
Result ShowFatalTask::ShowFatal() {
/* Pre-render the framebuffer. */
PreRenderFrameBuffer();
@ -459,14 +488,8 @@ namespace ams::fatal::srv {
R_ABORT_UNLESS(PrepareScreenForDrawing());
});
/* Dequeue a buffer. */
R_UNLESS(framebufferBegin(&this->fb, NULL) != nullptr, ResultNullGraphicsBuffer());
/* We've already pre-rendered the frame into the static buffer. */
/* ... */
/* Enqueue the buffer. */
framebufferEnd(&fb);
/* Display the pre-rendered frame. */
this->DisplayPreRenderedFrame();
return ResultSuccess();
}