diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 3988c6559..08f30c77e 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -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((display_width - layer_width) / 2); - const float layer_y = static_cast((display_height - layer_height) / 2); + const float layer_x = static_cast((display_width - LayerWidth) / 2); + const float layer_y = static_cast((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(); }