From c3dd456d513a989315d4e8a00ad8a1223bb8f9c4 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 17 Jul 2018 20:11:41 -0400 Subject: [PATCH] vi: Partially implement buffer crop parameters. --- .../service/nvdrv/devices/nvdisp_disp0.cpp | 6 +++-- .../hle/service/nvdrv/devices/nvdisp_disp0.h | 4 +++- .../hle/service/nvflinger/buffer_queue.cpp | 4 +++- src/core/hle/service/nvflinger/buffer_queue.h | 5 ++++- src/core/hle/service/nvflinger/nvflinger.cpp | 3 ++- src/core/hle/service/vi/vi.cpp | 14 ++++++++---- src/video_core/gpu.h | 1 + .../renderer_opengl/renderer_opengl.cpp | 22 +++++++++++++++---- .../renderer_opengl/renderer_opengl.h | 1 + 9 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index c39d5a164..ed69a4325 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -18,7 +18,8 @@ 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, NVFlinger::BufferQueue::BufferTransformFlags transform) { + u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform, + const MathUtil::Rectangle& crop_rect) { VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); LOG_WARNING(Service, "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}", @@ -26,7 +27,8 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 using PixelFormat = Tegra::FramebufferConfig::PixelFormat; const Tegra::FramebufferConfig framebuffer{ - addr, offset, width, height, stride, static_cast(format), transform}; + addr, offset, width, height, stride, static_cast(format), + transform, crop_rect}; Core::System::GetInstance().perf_stats.EndGameFrame(); diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index 3d3979723..d4631a32b 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h @@ -7,6 +7,7 @@ #include #include #include "common/common_types.h" +#include "common/math_util.h" #include "core/hle/service/nvdrv/devices/nvdevice.h" #include "core/hle/service/nvflinger/buffer_queue.h" @@ -23,7 +24,8 @@ public: /// 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, - NVFlinger::BufferQueue::BufferTransformFlags transform); + NVFlinger::BufferQueue::BufferTransformFlags transform, + const MathUtil::Rectangle& crop_rect); 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 a181cd2dc..7132b18ad 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -57,13 +57,15 @@ const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { return itr->igbp_buffer; } -void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform) { +void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, + const MathUtil::Rectangle& crop_rect) { 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; + itr->crop_rect = crop_rect; } 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 1e55b487e..004170538 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -6,6 +6,7 @@ #include #include +#include "common/math_util.h" #include "common/swap.h" #include "core/hle/kernel/event.h" @@ -68,12 +69,14 @@ public: Status status = Status::Free; IGBPBuffer igbp_buffer; BufferTransformFlags transform; + MathUtil::Rectangle crop_rect; }; void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer); boost::optional DequeueBuffer(u32 width, u32 height); const IGBPBuffer& RequestBuffer(u32 slot) const; - void QueueBuffer(u32 slot, BufferTransformFlags transform); + void QueueBuffer(u32 slot, BufferTransformFlags transform, + const MathUtil::Rectangle& crop_rect); 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 826646b7d..d580f779e 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -149,7 +149,8 @@ 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, buffer->transform); + igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->transform, + buffer->crop_rect); buffer_queue->ReleaseBuffer(buffer->slot); } diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index e094510bf..caef7e695 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -7,6 +7,7 @@ #include #include #include "common/alignment.h" +#include "common/math_util.h" #include "common/scope_exit.h" #include "core/core_timing.h" #include "core/hle/ipc_helpers.h" @@ -327,8 +328,8 @@ public: protected: void SerializeData() override { - // TODO(Subv): Figure out what this value means, writing non-zero here will make libnx try - // to read an IGBPBuffer object from the parcel. + // TODO(Subv): Figure out what this value means, writing non-zero here will make libnx + // try to read an IGBPBuffer object from the parcel. Write(1); WriteObject(buffer); Write(0); @@ -360,8 +361,8 @@ public: INSERT_PADDING_WORDS(3); u32_le timestamp; s32_le is_auto_timestamp; - s32_le crop_left; s32_le crop_top; + s32_le crop_left; s32_le crop_right; s32_le crop_bottom; s32_le scaling_mode; @@ -370,6 +371,10 @@ public: INSERT_PADDING_WORDS(2); u32_le fence_is_valid; std::array fences; + + MathUtil::Rectangle GetCropRect() const { + return {crop_left, crop_top, crop_right, crop_bottom}; + } }; static_assert(sizeof(Data) == 80, "ParcelData has wrong size"); @@ -519,7 +524,8 @@ private: } else if (transaction == TransactionId::QueueBuffer) { IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()}; - buffer_queue->QueueBuffer(request.data.slot, request.data.transform); + buffer_queue->QueueBuffer(request.data.slot, request.data.transform, + request.data.GetCropRect()); IGBPQueueBufferResponseParcel response{1280, 720}; ctx.WriteBuffer(response.Serialize()); diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index cc5ca656e..60930e997 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -67,6 +67,7 @@ struct FramebufferConfig { using TransformFlags = Service::NVFlinger::BufferQueue::BufferTransformFlags; TransformFlags transform_flags; + MathUtil::Rectangle crop_rect; }; namespace Engines { diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 1930fa6ef..7810b9147 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -154,6 +154,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf // Framebuffer orientation handling framebuffer_transform_flags = framebuffer.transform_flags; + framebuffer_crop_rect = framebuffer.crop_rect; // Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default // only allows rows to have a memory alignement of 4. @@ -320,11 +321,24 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, } } + ASSERT_MSG(framebuffer_crop_rect.top == 0, "Unimplemented"); + ASSERT_MSG(framebuffer_crop_rect.left == 0, "Unimplemented"); + + // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering + // (e.g. handheld mode) on a 1920x1080 framebuffer. + f32 scale_u = 1.f, scale_v = 1.f; + if (framebuffer_crop_rect.GetWidth() > 0) { + scale_u = static_cast(framebuffer_crop_rect.GetWidth()) / screen_info.texture.width; + } + if (framebuffer_crop_rect.GetHeight() > 0) { + scale_v = static_cast(framebuffer_crop_rect.GetHeight()) / screen_info.texture.height; + } + std::array vertices = {{ - ScreenRectVertex(x, y, texcoords.top, left), - ScreenRectVertex(x + w, y, texcoords.bottom, left), - ScreenRectVertex(x, y + h, texcoords.top, right), - ScreenRectVertex(x + w, y + h, texcoords.bottom, right), + ScreenRectVertex(x, y, texcoords.top * scale_u, left * scale_v), + ScreenRectVertex(x + w, y, texcoords.bottom * scale_u, left * scale_v), + ScreenRectVertex(x, y + h, texcoords.top * scale_u, right * scale_v), + ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v), }}; 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 fd0267cf5..59d92a3dc 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -97,4 +97,5 @@ private: /// Used for transforming the framebuffer orientation Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags; + MathUtil::Rectangle framebuffer_crop_rect; };