diff --git a/src/xenia/gpu/gl4/command_processor.cc b/src/xenia/gpu/gl4/command_processor.cc index 2017f2849..8d26f88e9 100644 --- a/src/xenia/gpu/gl4/command_processor.cc +++ b/src/xenia/gpu/gl4/command_processor.cc @@ -76,6 +76,8 @@ CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system) active_pixel_shader_(nullptr), active_framebuffer_(nullptr), last_framebuffer_texture_(0), + last_swap_width_(0), + last_swap_height_(0), point_list_geometry_program_(0), rect_list_geometry_program_(0), quad_list_geometry_program_(0), @@ -558,6 +560,11 @@ void CommandProcessor::ReturnFromWait() { } void CommandProcessor::IssueSwap() { + IssueSwap(last_swap_width_, last_swap_height_); +} + +void CommandProcessor::IssueSwap(uint32_t frontbuffer_width, + uint32_t frontbuffer_height) { if (!swap_handler_) { return; } @@ -576,14 +583,11 @@ void CommandProcessor::IssueSwap() { ? active_framebuffer_->color_targets[0] : last_framebuffer_texture_;*/ - // Guess frontbuffer dimensions. - // Command buffer seems to set these right before the XE_SWAP. - uint32_t window_scissor_tl = regs[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_TL].u32; - uint32_t window_scissor_br = regs[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_BR].u32; - swap_params.x = window_scissor_tl & 0x7FFF; - swap_params.y = (window_scissor_tl >> 16) & 0x7FFF; - swap_params.width = window_scissor_br & 0x7FFF - swap_params.x; - swap_params.height = (window_scissor_br >> 16) & 0x7FFF - swap_params.y; + // Frontbuffer dimensions, if valid. + swap_params.x = 0; + swap_params.y = 0; + swap_params.width = frontbuffer_width ? frontbuffer_width : 1280; + swap_params.height = frontbuffer_height ? frontbuffer_height : 720; PrepareForWait(); swap_handler_(swap_params); @@ -941,13 +945,17 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingbufferReader* reader, // interrupt. // 63 words here, but only the first has any data. uint32_t frontbuffer_ptr = reader->Read(); - reader->Advance(count - 1); + uint32_t frontbuffer_width = reader->Read(); + uint32_t frontbuffer_height = reader->Read(); + reader->Advance(count - 3); + last_swap_width_ = frontbuffer_width; + last_swap_height_ = frontbuffer_height; // Ensure we issue any pending draws. draw_batcher_.Flush(DrawBatcher::FlushMode::kMakeCoherent); if (swap_mode_ == SwapMode::kNormal) { - IssueSwap(); + IssueSwap(frontbuffer_width, frontbuffer_height); } if (trace_writer_.is_open()) { diff --git a/src/xenia/gpu/gl4/command_processor.h b/src/xenia/gpu/gl4/command_processor.h index 9f207dcb1..ffe7bd3cd 100644 --- a/src/xenia/gpu/gl4/command_processor.h +++ b/src/xenia/gpu/gl4/command_processor.h @@ -66,6 +66,7 @@ class CommandProcessor { void set_swap_mode(SwapMode swap_mode) { swap_mode_ = swap_mode; } void IssueSwap(); + void IssueSwap(uint32_t frontbuffer_width, uint32_t frontbuffer_height); void RequestFrameTrace(const std::wstring& root_path); void BeginTracing(const std::wstring& root_path); @@ -258,6 +259,8 @@ class CommandProcessor { GL4Shader* active_pixel_shader_; CachedFramebuffer* active_framebuffer_; GLuint last_framebuffer_texture_; + uint32_t last_swap_width_; + uint32_t last_swap_height_; std::vector cached_framebuffers_; std::vector cached_color_render_targets_; diff --git a/src/xenia/kernel/xboxkrnl_video.cc b/src/xenia/kernel/xboxkrnl_video.cc index 9dc3aa71c..ee29620e5 100644 --- a/src/xenia/kernel/xboxkrnl_video.cc +++ b/src/xenia/kernel/xboxkrnl_video.cc @@ -96,8 +96,8 @@ void xeVdQueryVideoMode(X_VIDEO_MODE* video_mode) { video_mode->is_widescreen = 1; video_mode->is_hi_def = 1; video_mode->refresh_rate = 60.0f; - video_mode->video_standard = 1; // NTSC - video_mode->unknown_0x8a = 0x94; // 0x8A; + video_mode->video_standard = 1; // NTSC + video_mode->unknown_0x8a = 0x94; // 0x8A; video_mode->unknown_0x01 = 0x01; video_mode->reserved[0] = video_mode->reserved[1] = video_mode->reserved[2] = 0; @@ -163,7 +163,8 @@ SHIM_CALL VdShutdownEngines_shim(PPCContext* ppc_state, KernelState* state) { SHIM_CALL VdGetGraphicsAsicID_shim(PPCContext* ppc_state, KernelState* state) { XELOGD("VdGetGraphicsAsicID()"); - // Games compare for < 0x10 and do VdInitializeEDRAM, else other (retrain/etc). + // Games compare for < 0x10 and do VdInitializeEDRAM, else other + // (retrain/etc). SHIM_SET_RETURN_64(0x11); } @@ -284,14 +285,14 @@ SHIM_CALL VdSetSystemCommandBufferGpuIdentifierAddress_shim( SHIM_CALL VdInitializeScalerCommandBuffer_shim(PPCContext* ppc_state, KernelState* state) { - uint32_t unk0 = SHIM_GET_ARG_32(0); // 0? - uint32_t unk1 = SHIM_GET_ARG_32(1); // 0x050002d0 size of ? - uint32_t unk2 = SHIM_GET_ARG_32(2); // 0? - uint32_t unk3 = SHIM_GET_ARG_32(3); // 0x050002d0 size of ? - uint32_t unk4 = SHIM_GET_ARG_32(4); // 0x050002d0 size of ? - uint32_t unk5 = SHIM_GET_ARG_32(5); // 7? - uint32_t unk6 = SHIM_GET_ARG_32(6); // 0x2004909c <-- points to zeros? - uint32_t unk7 = SHIM_GET_ARG_32(7); // 7? + uint32_t unk0 = SHIM_GET_ARG_32(0); // 0? + uint32_t unk1 = SHIM_GET_ARG_32(1); // 0x050002d0 size of ? + uint32_t unk2 = SHIM_GET_ARG_32(2); // 0? + uint32_t unk3 = SHIM_GET_ARG_32(3); // 0x050002d0 size of ? + uint32_t unk4 = SHIM_GET_ARG_32(4); // 0x050002d0 size of ? + uint32_t unk5 = SHIM_GET_ARG_32(5); // 7? + uint32_t unk6 = SHIM_GET_ARG_32(6); // 0x2004909c <-- points to zeros? + uint32_t unk7 = SHIM_GET_ARG_32(7); // 7? // arg8 is in stack! uint32_t sp = (uint32_t)ppc_state->r[1]; // Points to the first 80000000h where the memcpy sources from. @@ -315,6 +316,11 @@ SHIM_CALL VdInitializeScalerCommandBuffer_shim(PPCContext* ppc_state, SHIM_SET_RETURN_64(total_words >> 2); } +// We use these to shuffle data to VdSwap. +// This way it gets properly stored in the command buffer (for replay/etc). +static uint32_t last_frontbuffer_width_ = 1280; +static uint32_t last_frontbuffer_height_ = 720; + SHIM_CALL VdCallGraphicsNotificationRoutines_shim(PPCContext* ppc_state, KernelState* state) { uint32_t unk_1 = SHIM_GET_ARG_32(0); @@ -333,6 +339,10 @@ SHIM_CALL VdCallGraphicsNotificationRoutines_shim(PPCContext* ppc_state, // TODO(benvanik): what does this mean, I forget: // callbacks get 0, r3, r4 + // For use by VdSwap. + last_frontbuffer_width_ = fb_width; + last_frontbuffer_height_ = fb_height; + SHIM_SET_RETURN_64(0); } @@ -400,13 +410,16 @@ SHIM_CALL VdSwap_shim(PPCContext* ppc_state, KernelState* state) { (xe::gpu::xenos::PM4_XE_SWAP << 8)); dwords[1] = poly::byte_swap(frontbuffer); + // Set by VdCallGraphicsNotificationRoutines. + dwords[2] = poly::byte_swap(last_frontbuffer_width_); + dwords[3] = poly::byte_swap(last_frontbuffer_height_); + SHIM_SET_RETURN_64(0); } } // namespace kernel } // namespace xe - void xe::kernel::xboxkrnl::RegisterVideoExports(ExportResolver* export_resolver, KernelState* state) { SHIM_SET_MAPPING("xboxkrnl.exe", VdGetCurrentDisplayGamma, state);