diff --git a/app/src/main/cpp/skyline/gpu.cpp b/app/src/main/cpp/skyline/gpu.cpp index 80d3f214..16dc7409 100644 --- a/app/src/main/cpp/skyline/gpu.cpp +++ b/app/src/main/cpp/skyline/gpu.cpp @@ -12,6 +12,7 @@ namespace skyline::gpu { ANativeWindow_acquire(window); resolution.width = static_cast(ANativeWindow_getWidth(window)); resolution.height = static_cast(ANativeWindow_getHeight(window)); + format = ANativeWindow_getFormat(window); } GPU::~GPU() { @@ -23,38 +24,39 @@ namespace skyline::gpu { auto &buffer = bufferQueue.displayQueue.front(); bufferQueue.displayQueue.pop(); if (resolution != buffer->resolution || buffer->gbpBuffer.format != format) { - if (resolution != buffer->resolution && buffer->gbpBuffer.format != format) { - ANativeWindow_setBuffersGeometry(window, buffer->resolution.width, buffer->resolution.height, buffer->gbpBuffer.format); - resolution = buffer->resolution; - format = buffer->gbpBuffer.format; - } else if (resolution != buffer->resolution) { - ANativeWindow_setBuffersGeometry(window, buffer->resolution.width, buffer->resolution.height, format); - resolution = buffer->resolution; - } else if (buffer->gbpBuffer.format != format) { - ANativeWindow_setBuffersGeometry(window, resolution.width, resolution.height, buffer->gbpBuffer.format); - format = buffer->gbpBuffer.format; - } + ANativeWindow_setBuffersGeometry(window, buffer->resolution.width, buffer->resolution.height, buffer->gbpBuffer.format); + resolution = buffer->resolution; + format = buffer->gbpBuffer.format; } buffer->UpdateBuffer(); - auto bufferData = buffer->dataBuffer.data(); - //madvise(bufferData, buffer->gbpBuffer.size, MADV_SEQUENTIAL); (Uncomment this after deswizzling while reading sequentially instead of writing sequentially) + u8 *inBuffer = buffer->dataBuffer.data(); + madvise(inBuffer, buffer->gbpBuffer.size, MADV_SEQUENTIAL); ANativeWindow_Buffer windowBuffer; ARect rect; ANativeWindow_lock(window, &windowBuffer, &rect); - u32 *address = reinterpret_cast(windowBuffer.bits); - for (u32 y = 0; y < buffer->resolution.height; y++) { - for (u32 x = 0; x < buffer->resolution.width; x += 4, address += 4) { - u32 position = (y & 0x7f) >> 4U; - position += (x >> 4U) << 3U; - position += (y >> 7U) * ((resolution.width >> 4U) << 3U); - position *= 1024; - position += ((y & 0xf) >> 3U) << 9U; - position += ((x & 0xf) >> 3U) << 8U; - position += ((y & 0x7) >> 1U) << 6U; - position += ((x & 0x7) >> 2U) << 5U; - position += (y & 0x1) << 4U; - position += (x & 0x3) << 2U; - std::memcpy(address, bufferData + position, sizeof(u32) * 4); + u8 *outBuffer = reinterpret_cast(windowBuffer.bits); + const u32 strideBytes = buffer->gbpBuffer.stride * buffer->bpp; + const u32 blockHeight = 1U << buffer->gbpBuffer.blockHeightLog2; + const u32 blockHeightPixels = 8U << buffer->gbpBuffer.blockHeightLog2; + const u32 widthBlocks = strideBytes >> 6U; + const u32 heightBlocks = ((resolution.height) + blockHeightPixels - 1) >> (3 + buffer->gbpBuffer.blockHeightLog2); + for (u32 blockY = 0; blockY < heightBlocks; blockY++) { + for (u32 blockX = 0; blockX < widthBlocks; blockX++) { + for (u32 gobY = 0; gobY < blockHeight; gobY++) { + const u32 x = blockX * constant::GobStride; + const u32 y = blockY * blockHeightPixels + gobY * constant::GobHeight; + if (y < resolution.height) { + u8 *inBlock = inBuffer; + u8 *outBlock = outBuffer + (y * strideBytes) + x; + for (u32 i = 0; i < 32; i++) { + const u32 yT = ((i >> 1) & 0x06) | (i & 0x01); // NOLINT(hicpp-signed-bitwise) + const u32 xT = ((i << 3) & 0x10) | ((i << 1) & 0x20); // NOLINT(hicpp-signed-bitwise) + std::memcpy(outBlock + (yT * strideBytes) + xT, inBlock, sizeof(u128)); + inBlock += sizeof(u128); + } + } + inBuffer += constant::GobSize; + } } } ANativeWindow_unlockAndPost(window); diff --git a/app/src/main/cpp/skyline/gpu/display.cpp b/app/src/main/cpp/skyline/gpu/display.cpp index 18afdec4..6fbe3fe3 100644 --- a/app/src/main/cpp/skyline/gpu/display.cpp +++ b/app/src/main/cpp/skyline/gpu/display.cpp @@ -17,6 +17,17 @@ namespace skyline::gpu { if (!nvBuffer) throw exception("A QueueBuffer request has an invalid NVMap Handle ({}) and ID ({})", gbpBuffer.nvmapHandle, gbpBuffer.nvmapId); } + switch(gbpBuffer.format) { + case WINDOW_FORMAT_RGBA_8888: + case WINDOW_FORMAT_RGBX_8888: + bpp = sizeof(u32); + break; + case WINDOW_FORMAT_RGB_565: + bpp = sizeof(u16); + break; + default: + throw exception("Unknown pixel format used for FB"); + } } void Buffer::UpdateBuffer() { @@ -31,19 +42,18 @@ namespace skyline::gpu { void BufferQueue::RequestBuffer(Parcel &in, Parcel &out) { u32 slot = *reinterpret_cast(in.data.data() + constant::TokenLength); - auto buffer = queue.at(slot); out.WriteData(1); out.WriteData(sizeof(GbpBuffer)); out.WriteData(0); - out.WriteData(buffer->gbpBuffer); - state.logger->Debug("RequestBuffer: Slot: {}, Size: {}", slot, sizeof(GbpBuffer)); + out.WriteData(queue.at(slot)->gbpBuffer); + state.logger->Debug("RequestBuffer: Slot: {}", slot, sizeof(GbpBuffer)); } bool BufferQueue::DequeueBuffer(Parcel &in, Parcel &out, u64 address, u64 size) { auto *data = reinterpret_cast(in.data.data() + constant::TokenLength); i64 slot{-1}; for (auto &buffer : queue) { - if (buffer.second->status == BufferStatus::Free && buffer.second->resolution.width == data->width && buffer.second->resolution.height == data->height && buffer.second->gbpBuffer.format == data->format && buffer.second->gbpBuffer.usage == data->usage) { + if (buffer.second->status == BufferStatus::Free && buffer.second->resolution.width == data->width && buffer.second->resolution.height == data->height && buffer.second->gbpBuffer.usage == data->usage) { slot = buffer.first; buffer.second->status = BufferStatus::Dequeued; } @@ -51,7 +61,7 @@ namespace skyline::gpu { if (slot == -1) { state.thisThread->Sleep(); waitVec.emplace_back(state.thisThread, *data, address, size); - state.logger->Debug("DequeueBuffer: No Free Buffers"); + state.logger->Debug("DequeueBuffer: Width: {}, Height: {}, Format: {}, Usage: {}, Timestamps: {}, No Free Buffers", data->width, data->height, data->format, data->usage, data->timestamps); return true; } DequeueOut output(static_cast(slot)); @@ -86,8 +96,7 @@ namespace skyline::gpu { .height = buffer->gbpBuffer.height }; out.WriteData(output); - state.logger->Debug("QueueBuffer: Timestamp: {}, Auto Timestamp: {}, Crop: [T: {}, B: {}, L: {}, R: {}], Scaling Mode: {}, Transform: {}, Sticky Transform: {}, Swap Interval: {}, Slot: {}", data->timestamp, data->autoTimestamp, data->crop.top, data->crop.bottom, data->crop.left, data->crop.right, data->scalingMode, data->transform, data->stickyTransform, data->swapInterval, - data->slot); + state.logger->Debug("QueueBuffer: Timestamp: {}, Auto Timestamp: {}, Crop: [T: {}, B: {}, L: {}, R: {}], Scaling Mode: {}, Transform: {}, Sticky Transform: {}, Swap Interval: {}, Slot: {}", data->timestamp, data->autoTimestamp, data->crop.top, data->crop.bottom, data->crop.left, data->crop.right, data->scalingMode, data->transform, data->stickyTransform, data->swapInterval, data->slot); } void BufferQueue::CancelBuffer(Parcel &parcel) { @@ -96,6 +105,7 @@ namespace skyline::gpu { Fence fence[4]; } *data = reinterpret_cast(parcel.data.data() + constant::TokenLength); FreeBuffer(data->slot); + state.logger->Debug("CancelBuffer: Slot: {}", data->slot); } void BufferQueue::SetPreallocatedBuffer(Parcel &parcel) { @@ -110,8 +120,7 @@ namespace skyline::gpu { auto gbpBuffer = reinterpret_cast(pointer); queue[data->slot] = std::make_shared(state, data->slot, *gbpBuffer); state.gpu->bufferEvent->Signal(); - state.logger->Debug("SetPreallocatedBuffer: Slot: {}, Length: {}, Magic: 0x{:X}, Width: {}, Height: {}, Stride: {}, Format: {}, Usage: {}, Index: {}, ID: {}, Handle: {}, Offset: 0x{:X}, Block Height: {}", data->slot, data->length, gbpBuffer->magic, gbpBuffer->width, gbpBuffer->height, gbpBuffer->stride, gbpBuffer->format, gbpBuffer->usage, gbpBuffer->index, gbpBuffer->nvmapId, - gbpBuffer->nvmapHandle, gbpBuffer->offset, (1U << gbpBuffer->blockHeightLog2)); + state.logger->Debug("SetPreallocatedBuffer: Slot: {}, Magic: 0x{:X}, Width: {}, Height: {}, Stride: {}, Format: {}, Usage: {}, Index: {}, ID: {}, Handle: {}, Offset: 0x{:X}, Block Height: {}, Size: 0x{:X}", data->slot, gbpBuffer->magic, gbpBuffer->width, gbpBuffer->height, gbpBuffer->stride, gbpBuffer->format, gbpBuffer->usage, gbpBuffer->index,gbpBuffer->nvmapId, gbpBuffer->nvmapHandle, gbpBuffer->offset, (1U << gbpBuffer->blockHeightLog2), gbpBuffer->size); } void BufferQueue::FreeBuffer(u32 slotNo) { diff --git a/app/src/main/cpp/skyline/gpu/display.h b/app/src/main/cpp/skyline/gpu/display.h index 59e29f3c..da87c479 100644 --- a/app/src/main/cpp/skyline/gpu/display.h +++ b/app/src/main/cpp/skyline/gpu/display.h @@ -90,8 +90,8 @@ namespace skyline::gpu { * @brief This represents conditions for the completion of an asynchronous graphics operation */ struct Fence { - u32 syncptId; - u32 syncptValue; + u32 syncptId; //!< The ID of the syncpoint + u32 syncptValue; //!< The value of the syncpoint }; /** @@ -101,6 +101,7 @@ namespace skyline::gpu { public: const DeviceState &state; //!< The state of the device u32 slot; //!< The slot the buffer is in + u32 bpp; //!< The amount of bytes per pixel Resolution resolution; //!< The resolution of this buffer GbpBuffer gbpBuffer; //!< The information about the underlying buffer BufferStatus status{BufferStatus::Free}; //!< The status of this buffer diff --git a/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.cpp b/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.cpp index ee73047f..ec5c75dc 100644 --- a/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.cpp +++ b/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.cpp @@ -1,7 +1,6 @@ #include "dispdrv.h" #include #include -#include namespace skyline::service::nvnflinger { dispdrv::dispdrv(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::nvnflinger_dispdrv, {