Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
|
|
|
#include "gpu.h"
|
|
|
|
#include "gpu/devices/nvhost_ctrl.h"
|
|
|
|
#include "gpu/devices/nvhost_ctrl_gpu.h"
|
|
|
|
#include "gpu/devices/nvhost_channel.h"
|
|
|
|
#include "gpu/devices/nvhost_as_gpu.h"
|
|
|
|
#include <kernel/types/KProcess.h>
|
2019-12-02 18:40:53 +01:00
|
|
|
#include <android/native_window_jni.h>
|
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
|
|
|
|
|
|
|
extern bool Halt;
|
|
|
|
|
|
|
|
namespace skyline::gpu {
|
2019-12-02 18:40:53 +01:00
|
|
|
GPU::GPU(const DeviceState &state) : state(state), window(ANativeWindow_fromSurface(state.jvmManager->env, state.jvmManager->GetField("surface", "Landroid/view/Surface;"))), bufferQueue(state), vsyncEvent(std::make_shared<kernel::type::KEvent>(state)), bufferEvent(std::make_shared<kernel::type::KEvent>(state)) {
|
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
|
|
|
ANativeWindow_acquire(window);
|
|
|
|
resolution.width = static_cast<u32>(ANativeWindow_getWidth(window));
|
|
|
|
resolution.height = static_cast<u32>(ANativeWindow_getHeight(window));
|
2019-11-22 17:53:36 +01:00
|
|
|
format = ANativeWindow_getFormat(window);
|
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GPU::~GPU() {
|
|
|
|
ANativeWindow_release(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPU::Loop() {
|
2019-12-02 18:40:53 +01:00
|
|
|
if(state.jvmManager->CheckNull("surface", "Landroid/view/Surface;")) {
|
|
|
|
while (state.jvmManager->CheckNull("surface", "Landroid/view/Surface;")) {
|
|
|
|
if(state.jvmManager->GetField<jboolean>("halt"))
|
|
|
|
return;
|
|
|
|
sched_yield();
|
|
|
|
}
|
|
|
|
window = ANativeWindow_fromSurface(state.jvmManager->env, state.jvmManager->GetField("surface", "Landroid/view/Surface;"));
|
|
|
|
ANativeWindow_acquire(window);
|
|
|
|
resolution.width = static_cast<u32>(ANativeWindow_getWidth(window));
|
|
|
|
resolution.height = static_cast<u32>(ANativeWindow_getHeight(window));
|
|
|
|
format = ANativeWindow_getFormat(window);
|
|
|
|
}
|
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
|
|
|
if (!bufferQueue.displayQueue.empty()) {
|
|
|
|
auto &buffer = bufferQueue.displayQueue.front();
|
|
|
|
bufferQueue.displayQueue.pop();
|
|
|
|
if (resolution != buffer->resolution || buffer->gbpBuffer.format != format) {
|
2019-11-22 17:53:36 +01:00
|
|
|
ANativeWindow_setBuffersGeometry(window, buffer->resolution.width, buffer->resolution.height, buffer->gbpBuffer.format);
|
|
|
|
resolution = buffer->resolution;
|
|
|
|
format = buffer->gbpBuffer.format;
|
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
|
|
|
}
|
|
|
|
buffer->UpdateBuffer();
|
2019-11-22 17:53:36 +01:00
|
|
|
u8 *inBuffer = buffer->dataBuffer.data();
|
|
|
|
madvise(inBuffer, buffer->gbpBuffer.size, MADV_SEQUENTIAL);
|
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
|
|
|
ANativeWindow_Buffer windowBuffer;
|
|
|
|
ARect rect;
|
|
|
|
ANativeWindow_lock(window, &windowBuffer, &rect);
|
2019-11-22 17:53:36 +01:00
|
|
|
u8 *outBuffer = reinterpret_cast<u8 *>(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;
|
|
|
|
}
|
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ANativeWindow_unlockAndPost(window);
|
|
|
|
bufferQueue.FreeBuffer(buffer->slot);
|
|
|
|
vsyncEvent->Signal();
|
|
|
|
if (prevTime != 0) {
|
|
|
|
auto now = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
|
|
|
state.logger->Error("{} ms, {} FPS", (now - prevTime) / 1000, 1000000 / (now - prevTime));
|
|
|
|
}
|
|
|
|
prevTime = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 GPU::OpenDevice(const std::string &path) {
|
|
|
|
state.logger->Debug("Opening NVDRV device ({}): {}", fdIndex, path);
|
|
|
|
auto type = device::nvDeviceMap.at(path);
|
|
|
|
for (const auto &device : fdMap) {
|
|
|
|
if (device.second->deviceType == type) {
|
|
|
|
device.second->refCount++;
|
|
|
|
fdMap[fdIndex] = device.second;
|
|
|
|
return fdIndex++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::shared_ptr<device::NvDevice> object;
|
|
|
|
switch (type) {
|
|
|
|
case (device::NvDeviceType::nvhost_ctrl):
|
|
|
|
object = std::make_shared<device::NvHostCtrl>(state);
|
|
|
|
break;
|
|
|
|
case (device::NvDeviceType::nvhost_gpu):
|
|
|
|
case (device::NvDeviceType::nvhost_vic):
|
|
|
|
case (device::NvDeviceType::nvhost_nvdec):
|
|
|
|
object = std::make_shared<device::NvHostChannel>(state, type);
|
|
|
|
break;
|
|
|
|
case (device::NvDeviceType::nvhost_ctrl_gpu):
|
|
|
|
object = std::make_shared<device::NvHostCtrlGpu>(state);
|
|
|
|
break;
|
|
|
|
case (device::NvDeviceType::nvmap):
|
|
|
|
object = std::make_shared<device::NvMap>(state);
|
|
|
|
break;
|
|
|
|
case (device::NvDeviceType::nvhost_as_gpu):
|
|
|
|
object = std::make_shared<device::NvHostAsGpu>(state);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw exception("Cannot find NVDRV device");
|
|
|
|
}
|
|
|
|
deviceMap[type] = object;
|
|
|
|
fdMap[fdIndex] = object;
|
|
|
|
return fdIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPU::CloseDevice(u32 fd) {
|
|
|
|
state.logger->Debug("Closing NVDRV device ({})", fd);
|
|
|
|
try {
|
|
|
|
auto device = fdMap.at(fd);
|
|
|
|
if (!--device->refCount)
|
|
|
|
deviceMap.erase(device->deviceType);
|
|
|
|
fdMap.erase(fd);
|
|
|
|
} catch (const std::out_of_range &) {
|
|
|
|
state.logger->Warn("Trying to close non-existent FD");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPU::Ioctl(u32 fd, u32 cmd, kernel::ipc::IpcRequest &request, kernel::ipc::IpcResponse &response) {
|
|
|
|
state.logger->Debug("IOCTL on device: 0x{:X}, cmd: 0x{:X}", fd, cmd);
|
|
|
|
try {
|
2019-11-23 19:48:22 +01:00
|
|
|
if(request.inputBuf.empty() || request.outputBuf.empty()) {
|
|
|
|
if(request.inputBuf.empty()) {
|
|
|
|
device::IoctlData data(request.outputBuf.at(0));
|
|
|
|
fdMap.at(fd)->HandleIoctl(cmd, data);
|
|
|
|
response.Push<u32>(data.status);
|
|
|
|
} else {
|
|
|
|
device::IoctlData data(request.inputBuf.at(0));
|
|
|
|
fdMap.at(fd)->HandleIoctl(cmd, data);
|
|
|
|
response.Push<u32>(data.status);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
device::IoctlData data(request.inputBuf.at(0), request.outputBuf.at(0));
|
|
|
|
fdMap.at(fd)->HandleIoctl(cmd, data);
|
|
|
|
response.Push<u32>(data.status);
|
|
|
|
}
|
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
|
|
|
} catch (const std::out_of_range &) {
|
|
|
|
throw exception("IOCTL was requested on an invalid file descriptor");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPU::SetDisplay(const std::string &name) {
|
|
|
|
try {
|
|
|
|
const auto type = displayTypeMap.at(name);
|
|
|
|
if (displayId == DisplayId::Null)
|
|
|
|
displayId = type;
|
|
|
|
else
|
|
|
|
throw exception("Trying to change display type from non-null type");
|
|
|
|
} catch (const std::out_of_range &) {
|
|
|
|
throw exception("The display with name: '{}' doesn't exist", name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPU::CloseDisplay() {
|
|
|
|
if (displayId == DisplayId::Null)
|
|
|
|
state.logger->Warn("Trying to close uninitiated display");
|
|
|
|
displayId = DisplayId::Null;
|
|
|
|
}
|
|
|
|
}
|