| 330 | } |
| 331 | |
| 332 | void CtrUi::UpdateDisplay() { |
| 333 | // convert ARGB buffer to RGBA buffer |
| 334 | // required because pixman has no fast-paths for non AXXX buffers and 3DS wants RGBA |
| 335 | screen_surface->BlitFast(0, 0, *main_surface, main_surface->GetRect(), Opacity::Opaque()); |
| 336 | |
| 337 | GSPGPU_FlushDataCache(screen_buffer, tex.width * tex.height * 4); |
| 338 | |
| 339 | // Convert the texture before starting a frame, so this uses a safe transfer |
| 340 | // Using RGB8 as output format is faster and improves framerate ¯\_(ツ)_/¯ |
| 341 | u32 dim = GX_BUFFER_DIM(tex.width, tex.height); |
| 342 | C3D_SyncDisplayTransfer(screen_buffer, dim, (u32*)tex.data, dim, |
| 343 | (GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | |
| 344 | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | |
| 345 | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)) |
| 346 | ); |
| 347 | |
| 348 | // start frame, clear targets |
| 349 | C3D_FrameBegin(C3D_FRAME_SYNCDRAW); |
| 350 | C2D_TargetClear(top_screen, C2D_Color32f(0, 0, 0, 1)); |
| 351 | #ifndef _DEBUG |
| 352 | // only clear if needed |
| 353 | if (bottom_state > screen_state::keep) |
| 354 | C2D_TargetClear(bottom_screen, C2D_Color32f(0, 0, 0, 1)); |
| 355 | #endif |
| 356 | |
| 357 | // top screen |
| 358 | C2D_SceneBegin(top_screen); |
| 359 | |
| 360 | C2D_Image img = { &tex, &subt3x }; |
| 361 | if (vcfg.stretch.Get()) { |
| 362 | C2D_DrawImageAt(img, 0, 0, z, nullptr, renderer.stretch_x, renderer.stretch_y); |
| 363 | } else { |
| 364 | C2D_DrawImageAt(img, renderer.left, renderer.top, z); |
| 365 | } |
| 366 | |
| 367 | // bottom screen |
| 368 | #ifndef _DEBUG |
| 369 | // darkened button with outline |
| 370 | auto draw_button = [this](Point p, int w, int h) { |
| 371 | u8 col = p.x / w; |
| 372 | u8 row = p.y / h; |
| 373 | int x = col * w; |
| 374 | int y = row * h; |
| 375 | int b = 2; // border width |
| 376 | int z = 0.6f; |
| 377 | constexpr u32 white = C2D_Color32f(1, 1, 1, 1); |
| 378 | constexpr u32 darkgray = C2D_Color32f(0.5f, 0.5f, 0.5f, 1); |
| 379 | constexpr u32 lightgray = C2D_Color32f(0.8f, 0.8f, 0.8f, 1); |
| 380 | constexpr u32 transblack = C2D_Color32f(0, 0, 0, 0.3f); |
| 381 | |
| 382 | C2D_DrawRectSolid(x + b, y + b, z, w - b * 2, h - b * 2, transblack); // inner layer |
| 383 | C2D_DrawRectangle(x, y, z, w, b, darkgray, lightgray, darkgray, lightgray); // top |
| 384 | C2D_DrawRectangle(x, y, z, b, h, darkgray, darkgray, lightgray, lightgray); // left |
| 385 | C2D_DrawRectangle(x + w - b, y, z, b, h, lightgray, lightgray, white, white); // right |
| 386 | C2D_DrawRectangle(x, y + h - b, z, w, b, lightgray, white, lightgray, white); // bottom |
| 387 | }; |
| 388 | |
| 389 | // "circle" cursor |