skyline/app/src/main/cpp/skyline/gpu.cpp

75 lines
2.8 KiB
C++

// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include "gpu.h"
#include "jvm.h"
#include <kernel/types/KProcess.h>
#include <android/native_window_jni.h>
extern bool Halt;
extern jobject Surface;
extern skyline::u16 fps;
extern skyline::u32 frametime;
namespace skyline::gpu {
GPU::GPU(const DeviceState &state) : state(state), window(ANativeWindow_fromSurface(state.jvm->GetEnv(), Surface)), vsyncEvent(std::make_shared<kernel::type::KEvent>(state)), bufferEvent(std::make_shared<kernel::type::KEvent>(state)) {
ANativeWindow_acquire(window);
resolution.width = static_cast<u32>(ANativeWindow_getWidth(window));
resolution.height = static_cast<u32>(ANativeWindow_getHeight(window));
format = ANativeWindow_getFormat(window);
}
GPU::~GPU() {
ANativeWindow_release(window);
}
void GPU::Loop() {
if (surfaceUpdate) {
if (Surface == nullptr)
return;
window = ANativeWindow_fromSurface(state.jvm->GetEnv(), Surface);
ANativeWindow_acquire(window);
resolution.width = static_cast<u32>(ANativeWindow_getWidth(window));
resolution.height = static_cast<u32>(ANativeWindow_getHeight(window));
format = ANativeWindow_getFormat(window);
surfaceUpdate = false;
} else if (Surface == nullptr) {
surfaceUpdate = true;
return;
}
if (!presentationQueue.empty()) {
auto &texture = presentationQueue.front();
presentationQueue.pop();
auto textureFormat = texture->GetAndroidFormat();
if (resolution != texture->dimensions || textureFormat != format) {
ANativeWindow_setBuffersGeometry(window, texture->dimensions.width, texture->dimensions.height, textureFormat);
resolution = texture->dimensions;
format = textureFormat;
}
ANativeWindow_Buffer windowBuffer;
ARect rect;
ANativeWindow_lock(window, &windowBuffer, &rect);
std::memcpy(windowBuffer.bits, texture->backing.data(), texture->backing.size());
ANativeWindow_unlockAndPost(window);
vsyncEvent->Signal();
texture->releaseCallback();
if (frameTimestamp) {
auto now = util::GetTimeNs();
frametime = static_cast<u32>((now - frameTimestamp) / 10000); // frametime / 100 is the real ms value, this is to retain the first two decimals
fps = static_cast<u16>(1000000000 / (now - frameTimestamp));
frameTimestamp = now;
} else {
frameTimestamp = util::GetTimeNs();
}
}
}
}