From 068744db1bfddea0d49fb3ae120383b151011ebf Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 11 Feb 2018 17:28:07 -0500 Subject: [PATCH 1/3] vi: Fix OpenLayer and CreateStrayLayer. --- src/core/hle/service/vi/vi.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 69ac2fe07..0262e830b 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -101,8 +101,10 @@ public: SerializeData(); Header header{}; - header.data_offset = sizeof(Header); header.data_size = static_cast(write_index - sizeof(Header)); + header.data_offset = sizeof(Header); + header.objects_size = 4; + header.objects_offset = sizeof(Header) + header.data_size; std::memcpy(buffer.data(), &header, sizeof(Header)); return buffer; @@ -142,11 +144,11 @@ protected: private: struct Data { u32_le magic = 2; - u32_le process_id; + u32_le process_id = 1; u32_le id; - INSERT_PADDING_BYTES(0xC); + INSERT_PADDING_WORDS(3); std::array dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'}; - INSERT_PADDING_BYTES(8); + INSERT_PADDING_WORDS(2); }; static_assert(sizeof(Data) == 0x28, "ParcelData has wrong size"); @@ -672,7 +674,7 @@ void IApplicationDisplayService::CloseDisplay(Kernel::HLERequestContext& ctx) { } void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); + LOG_DEBUG(Service_VI, "called"); IPC::RequestParser rp{ctx}; auto name_buf = rp.PopRaw>(); auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); @@ -697,7 +699,7 @@ void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { } void IApplicationDisplayService::CreateStrayLayer(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service, "(STUBBED) called"); + LOG_DEBUG(Service_VI, "called"); IPC::RequestParser rp{ctx}; u32 flags = rp.Pop(); From 6fce1414c3a899c3694fd05518101a82ff8060ce Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 11 Feb 2018 19:03:31 -0500 Subject: [PATCH 2/3] vi: Parse IGBPQueueBufferRequestParcel params and expose buffer flip vertical. --- .../service/nvdrv/devices/nvdisp_disp0.cpp | 6 +++-- .../hle/service/nvdrv/devices/nvdisp_disp0.h | 4 ++- .../hle/service/nvflinger/buffer_queue.cpp | 3 ++- src/core/hle/service/nvflinger/buffer_queue.h | 16 +++++++++++- src/core/hle/service/nvflinger/nvflinger.cpp | 2 +- src/core/hle/service/vi/vi.cpp | 26 +++++++++++++++---- 6 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 4d0ab844c..7674d332d 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -20,15 +20,17 @@ u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector& input, std::vector } void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, - u32 stride) { + u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform) { VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); LOG_WARNING(Service, "Drawing from address %llx offset %08X Width %u Height %u Stride %u Format %u", addr, offset, width, height, stride, format); using PixelFormat = RendererBase::FramebufferInfo::PixelFormat; + using Flags = NVFlinger::BufferQueue::BufferTransformFlags; + const bool flip_vertical = static_cast(transform) & static_cast(Flags::FlipV); const RendererBase::FramebufferInfo framebuffer_info{ - addr, offset, width, height, stride, static_cast(format)}; + addr, offset, width, height, stride, static_cast(format), flip_vertical}; Core::System::GetInstance().perf_stats.EndGameFrame(); VideoCore::g_renderer->SwapBuffers(framebuffer_info); diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index f3cfc9925..66f56f23d 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h @@ -8,6 +8,7 @@ #include #include "common/common_types.h" #include "core/hle/service/nvdrv/devices/nvdevice.h" +#include "core/hle/service/nvflinger/buffer_queue.h" namespace Service { namespace Nvidia { @@ -23,7 +24,8 @@ public: u32 ioctl(Ioctl command, const std::vector& input, std::vector& output) override; /// Performs a screen flip, drawing the buffer pointed to by the handle. - void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride); + void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride, + NVFlinger::BufferQueue::BufferTransformFlags transform); private: std::shared_ptr nvmap_dev; diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index f90c7ca51..ff7b6b039 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -58,12 +58,13 @@ const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { return itr->igbp_buffer; } -void BufferQueue::QueueBuffer(u32 slot) { +void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform) { auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { return buffer.slot == slot; }); ASSERT(itr != queue.end()); ASSERT(itr->status == Buffer::Status::Dequeued); itr->status = Buffer::Status::Queued; + itr->transform = transform; } boost::optional BufferQueue::AcquireBuffer() { diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 5c6719407..ef9732769 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -46,18 +46,32 @@ public: BufferQueue(u32 id, u64 layer_id); ~BufferQueue() = default; + enum class BufferTransformFlags : u32 { + /// Flip source image horizontally (around the vertical axis) + FlipH = 0x01, + /// Flip source image vertically (around the horizontal axis) + FlipV = 0x02, + /// Rotate source image 90 degrees clockwise + Rotate90 = 0x04, + /// Rotate source image 180 degrees + Roate180 = 0x03, + /// Rotate source image 270 degrees clockwise + Roate270 = 0x07, + }; + struct Buffer { enum class Status { Free = 0, Queued = 1, Dequeued = 2, Acquired = 3 }; u32 slot; Status status = Status::Free; IGBPBuffer igbp_buffer; + BufferTransformFlags transform; }; void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer); u32 DequeueBuffer(u32 pixel_format, u32 width, u32 height); const IGBPBuffer& RequestBuffer(u32 slot) const; - void QueueBuffer(u32 slot); + void QueueBuffer(u32 slot, BufferTransformFlags transform); boost::optional AcquireBuffer(); void ReleaseBuffer(u32 slot); u32 Query(QueryType type); diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index fe622b986..2089462b7 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -145,7 +145,7 @@ void NVFlinger::Compose() { ASSERT(nvdisp); nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format, - igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride); + igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->transform); buffer_queue->ReleaseBuffer(buffer->slot); } diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 0262e830b..dd4d3e517 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -3,7 +3,7 @@ // Refer to the license.txt file included. #include - +#include #include "common/alignment.h" #include "common/scope_exit.h" #include "core/core_timing.h" @@ -325,13 +325,29 @@ public: data = Read(); } + struct Fence { + u32_le id; + u32_le value; + }; + static_assert(sizeof(Fence) == 8, "Fence has wrong size"); + struct Data { u32_le slot; - INSERT_PADDING_WORDS(2); + INSERT_PADDING_WORDS(3); u32_le timestamp; - INSERT_PADDING_WORDS(20); + s32_le is_auto_timestamp; + s32_le crop_left; + s32_le crop_top; + s32_le crop_right; + s32_le crop_bottom; + s32_le scaling_mode; + NVFlinger::BufferQueue::BufferTransformFlags transform; + u32_le sticky_transform; + INSERT_PADDING_WORDS(2); + u32_le fence_is_valid; + std::array fences; }; - static_assert(sizeof(Data) == 96, "ParcelData has wrong size"); + static_assert(sizeof(Data) == 80, "ParcelData has wrong size"); Data data; }; @@ -456,7 +472,7 @@ private: } else if (transaction == TransactionId::QueueBuffer) { IGBPQueueBufferRequestParcel request{input_data}; - buffer_queue->QueueBuffer(request.data.slot); + buffer_queue->QueueBuffer(request.data.slot, request.data.transform); IGBPQueueBufferResponseParcel response{1280, 720}; response_buffer = response.Serialize(); From deadcb39c2914d77734907daf7ce304872265798 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 11 Feb 2018 19:04:27 -0500 Subject: [PATCH 3/3] renderer_opengl: Support framebuffer flip vertical. --- src/video_core/renderer_base.h | 1 + src/video_core/renderer_opengl/renderer_opengl.cpp | 14 +++++++++----- src/video_core/renderer_opengl/renderer_opengl.h | 3 +++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 28893b181..2aba50eda 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -43,6 +43,7 @@ public: u32 height; u32 stride; PixelFormat pixel_format; + bool flip_vertical; }; virtual ~RendererBase() {} diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 8c23128ae..7f921fa32 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -262,6 +262,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, // only allows rows to have a memory alignement of 4. ASSERT(framebuffer_info.stride % 4 == 0); + framebuffer_flip_vertical = framebuffer_info.flip_vertical; + // Reset the screen info's display texture to its own permanent texture screen_info.display_texture = screen_info.texture.resource.handle; screen_info.display_texcoords = MathUtil::Rectangle(0.f, 0.f, 1.f, 1.f); @@ -401,13 +403,15 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h) { - auto& texcoords = screen_info.display_texcoords; + const auto& texcoords = screen_info.display_texcoords; + const auto& left = framebuffer_flip_vertical ? texcoords.right : texcoords.left; + const auto& right = framebuffer_flip_vertical ? texcoords.left : texcoords.right; std::array vertices = {{ - ScreenRectVertex(x, y, texcoords.top, texcoords.right), - ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.right), - ScreenRectVertex(x, y + h, texcoords.top, texcoords.left), - ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.left), + ScreenRectVertex(x, y, texcoords.top, right), + ScreenRectVertex(x + w, y, texcoords.bottom, right), + ScreenRectVertex(x, y + h, texcoords.top, left), + ScreenRectVertex(x + w, y + h, texcoords.bottom, left), }}; state.texture_units[0].texture_2d = screen_info.display_texture; diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index db6c355a5..05bb3c5cf 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -86,4 +86,7 @@ private: // Shader attribute input indices GLuint attrib_position; GLuint attrib_tex_coord; + + /// Flips the framebuffer vertically when true + bool framebuffer_flip_vertical; };