mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Android: Reduce asserts during startup.
This commit is contained in:
parent
aebbff55f1
commit
73166def93
9 changed files with 124 additions and 74 deletions
103
UI/NativeApp.cpp
103
UI/NativeApp.cpp
|
@ -803,29 +803,34 @@ static void UIThemeInit() {
|
|||
}
|
||||
|
||||
void RenderOverlays(UIContext *dc, void *userdata);
|
||||
bool CreateGlobalPipelines();
|
||||
|
||||
bool NativeInitGraphics(GraphicsContext *graphicsContext) {
|
||||
ILOG("NativeInitGraphics");
|
||||
_assert_msg_(graphicsContext, "No graphics context!");
|
||||
|
||||
// We set this now so any resize during init is processed later.
|
||||
resized = false;
|
||||
|
||||
using namespace Draw;
|
||||
Core_SetGraphicsContext(graphicsContext);
|
||||
g_draw = graphicsContext->GetDrawContext();
|
||||
_assert_msg_(g_draw, "No draw context available!");
|
||||
_assert_msg_(g_draw->GetVshaderPreset(VS_COLOR_2D) != nullptr, "Failed to compile presets");
|
||||
|
||||
if (!CreateGlobalPipelines()) {
|
||||
ERROR_LOG(G3D, "Failed to create global pipelines");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the atlas.
|
||||
|
||||
size_t atlas_data_size = 0;
|
||||
if (!g_ui_atlas.IsMetadataLoaded()) {
|
||||
const uint8_t *atlas_data = VFSReadFile("ui_atlas.meta", &atlas_data_size);
|
||||
bool load_success = atlas_data != nullptr && g_ui_atlas.Load(atlas_data, atlas_data_size);
|
||||
_assert_msg_(load_success, "Failed to load ui_atlas.meta");
|
||||
if (!load_success) {
|
||||
ERROR_LOG(G3D, "Failed to load ui_atlas.meta - graphics will be broken.");
|
||||
// Stumble along with broken visuals instead of dying.
|
||||
}
|
||||
delete[] atlas_data;
|
||||
}
|
||||
|
||||
ui_draw2d.SetAtlas(&g_ui_atlas);
|
||||
ui_draw2d_front.SetAtlas(&g_ui_atlas);
|
||||
|
||||
|
@ -834,43 +839,10 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) {
|
|||
uiContext = new UIContext();
|
||||
uiContext->theme = &ui_theme;
|
||||
|
||||
Draw::InputLayout *inputLayout = ui_draw2d.CreateInputLayout(g_draw);
|
||||
Draw::BlendState *blendNormal = g_draw->CreateBlendState({ true, 0xF, BlendFactor::SRC_ALPHA, BlendFactor::ONE_MINUS_SRC_ALPHA });
|
||||
Draw::DepthStencilState *depth = g_draw->CreateDepthStencilState({ false, false, Comparison::LESS });
|
||||
Draw::RasterState *rasterNoCull = g_draw->CreateRasterState({});
|
||||
|
||||
PipelineDesc colorDesc{
|
||||
Primitive::TRIANGLE_LIST,
|
||||
{ g_draw->GetVshaderPreset(VS_COLOR_2D), g_draw->GetFshaderPreset(FS_COLOR_2D) },
|
||||
inputLayout, depth, blendNormal, rasterNoCull, &vsColBufDesc,
|
||||
};
|
||||
PipelineDesc texColorDesc{
|
||||
Primitive::TRIANGLE_LIST,
|
||||
{ g_draw->GetVshaderPreset(VS_TEXTURE_COLOR_2D), g_draw->GetFshaderPreset(FS_TEXTURE_COLOR_2D) },
|
||||
inputLayout, depth, blendNormal, rasterNoCull, &vsTexColBufDesc,
|
||||
};
|
||||
|
||||
colorPipeline = g_draw->CreateGraphicsPipeline(colorDesc);
|
||||
texColorPipeline = g_draw->CreateGraphicsPipeline(texColorDesc);
|
||||
|
||||
_assert_(colorPipeline);
|
||||
_assert_(texColorPipeline);
|
||||
|
||||
// Release these now, reference counting should ensure that they get completely released
|
||||
// once we delete both pipelines.
|
||||
inputLayout->Release();
|
||||
rasterNoCull->Release();
|
||||
blendNormal->Release();
|
||||
depth->Release();
|
||||
|
||||
ui_draw2d.Init(g_draw, texColorPipeline);
|
||||
ui_draw2d_front.Init(g_draw, texColorPipeline);
|
||||
|
||||
uiContext->Init(g_draw, texColorPipeline, colorPipeline, &ui_draw2d, &ui_draw2d_front);
|
||||
RasterStateDesc desc;
|
||||
desc.cull = CullMode::NONE;
|
||||
desc.frontFace = Facing::CCW;
|
||||
|
||||
if (uiContext->Text())
|
||||
uiContext->Text()->SetFont("Tahoma", 20, 0);
|
||||
|
||||
|
@ -897,13 +869,54 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) {
|
|||
|
||||
g_gameInfoCache = new GameInfoCache();
|
||||
|
||||
if (gpu)
|
||||
if (gpu) {
|
||||
gpu->DeviceRestore();
|
||||
}
|
||||
|
||||
ILOG("NativeInitGraphics completed");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CreateGlobalPipelines() {
|
||||
using namespace Draw;
|
||||
|
||||
InputLayout *inputLayout = ui_draw2d.CreateInputLayout(g_draw);
|
||||
BlendState *blendNormal = g_draw->CreateBlendState({ true, 0xF, BlendFactor::SRC_ALPHA, BlendFactor::ONE_MINUS_SRC_ALPHA });
|
||||
DepthStencilState *depth = g_draw->CreateDepthStencilState({ false, false, Comparison::LESS });
|
||||
RasterState *rasterNoCull = g_draw->CreateRasterState({});
|
||||
|
||||
PipelineDesc colorDesc{
|
||||
Primitive::TRIANGLE_LIST,
|
||||
{ g_draw->GetVshaderPreset(VS_COLOR_2D), g_draw->GetFshaderPreset(FS_COLOR_2D) },
|
||||
inputLayout, depth, blendNormal, rasterNoCull, &vsColBufDesc,
|
||||
};
|
||||
PipelineDesc texColorDesc{
|
||||
Primitive::TRIANGLE_LIST,
|
||||
{ g_draw->GetVshaderPreset(VS_TEXTURE_COLOR_2D), g_draw->GetFshaderPreset(FS_TEXTURE_COLOR_2D) },
|
||||
inputLayout, depth, blendNormal, rasterNoCull, &vsTexColBufDesc,
|
||||
};
|
||||
|
||||
colorPipeline = g_draw->CreateGraphicsPipeline(colorDesc);
|
||||
if (!colorPipeline) {
|
||||
// Something really critical is wrong, don't care much about correct releasing of the states.
|
||||
return false;
|
||||
}
|
||||
|
||||
texColorPipeline = g_draw->CreateGraphicsPipeline(texColorDesc);
|
||||
if (!texColorPipeline) {
|
||||
// Something really critical is wrong, don't care much about correct releasing of the states.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Release these now, reference counting should ensure that they get completely released
|
||||
// once we delete both pipelines.
|
||||
inputLayout->Release();
|
||||
rasterNoCull->Release();
|
||||
blendNormal->Release();
|
||||
depth->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeShutdownGraphics() {
|
||||
screenManager->deviceLost();
|
||||
|
||||
|
@ -912,12 +925,12 @@ void NativeShutdownGraphics() {
|
|||
|
||||
ILOG("NativeShutdownGraphics");
|
||||
|
||||
#ifdef _WIN32
|
||||
#if PPSSPP_PLATFORM(WINDOWS)
|
||||
delete winAudioBackend;
|
||||
winAudioBackend = nullptr;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
|
||||
if (winCamera) {
|
||||
winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::SHUTDOWN, nullptr });
|
||||
while (!winCamera->isShutDown()) {};// Wait for shutting down.
|
||||
|
@ -1086,7 +1099,7 @@ void NativeRender(GraphicsContext *graphicsContext) {
|
|||
screenManager->resized();
|
||||
|
||||
// TODO: Move this to the GraphicsContext objects for each backend.
|
||||
#if !defined(_WIN32) && !defined(ANDROID)
|
||||
#if !PPSSPP_PLATFORM(WINDOWS) && !defined(ANDROID)
|
||||
PSP_CoreParameter().pixelWidth = pixel_xres;
|
||||
PSP_CoreParameter().pixelHeight = pixel_yres;
|
||||
NativeMessageReceived("gpu_resized", "");
|
||||
|
@ -1133,7 +1146,7 @@ void HandleGlobalMessage(const std::string &msg, const std::string &value) {
|
|||
if (msg == "core_powerSaving") {
|
||||
if (value != "false") {
|
||||
auto sy = GetI18NCategory("System");
|
||||
#ifdef __ANDROID__
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
osm.Show(sy->T("WARNING: Android battery save mode is on"), 2.0f, 0xFFFFFF, -1, true, "core_powerSaving");
|
||||
#else
|
||||
osm.Show(sy->T("WARNING: Battery save mode is on"), 2.0f, 0xFFFFFF, -1, true, "core_powerSaving");
|
||||
|
@ -1142,7 +1155,7 @@ void HandleGlobalMessage(const std::string &msg, const std::string &value) {
|
|||
Core_SetPowerSaving(value != "false");
|
||||
}
|
||||
if (msg == "permission_granted" && value == "storage") {
|
||||
#ifdef __ANDROID__
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
CreateDirectoriesAndroid();
|
||||
#endif
|
||||
// We must have failed to load the config before, so load it now to avoid overwriting the old config
|
||||
|
|
|
@ -399,17 +399,23 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) {
|
|||
pauseRequested = false;
|
||||
resumeRequested = false;
|
||||
|
||||
CheckGLExtensions();
|
||||
draw_ = Draw::T3DCreateGLContext();
|
||||
bool success = draw_->CreatePresets(); // if we get this far, there will always be a GLSL compiler capable of compiling these.
|
||||
if (!success) {
|
||||
delete draw_;
|
||||
draw_ = nullptr;
|
||||
ReleaseGLContext();
|
||||
return false;
|
||||
}
|
||||
|
||||
// These are auto-reset events.
|
||||
pauseEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
resumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
|
||||
CheckGLExtensions();
|
||||
draw_ = Draw::T3DCreateGLContext();
|
||||
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
renderManager_->SetInflightFrames(g_Config.iInflightFrames);
|
||||
SetGPUBackend(GPUBackend::OPENGL);
|
||||
bool success = draw_->CreatePresets(); // if we get this far, there will always be a GLSL compiler capable of compiling these.
|
||||
_assert_msg_(success, "Failed to compile preset shaders");
|
||||
renderManager_->SetSwapFunction([&]() {::SwapBuffers(hDC); });
|
||||
if (wglSwapIntervalEXT) {
|
||||
// glew loads wglSwapIntervalEXT if available
|
||||
|
@ -430,14 +436,10 @@ void WindowsGLContext::Shutdown() {
|
|||
glslang::FinalizeProcess();
|
||||
}
|
||||
|
||||
void WindowsGLContext::ShutdownFromRenderThread() {
|
||||
delete draw_;
|
||||
draw_ = nullptr;
|
||||
CloseHandle(pauseEvent);
|
||||
CloseHandle(resumeEvent);
|
||||
void WindowsGLContext::ReleaseGLContext() {
|
||||
if (hRC) {
|
||||
// Are we able to release the DC and RC contexts?
|
||||
if (!wglMakeCurrent(NULL,NULL)) {
|
||||
if (!wglMakeCurrent(NULL, NULL)) {
|
||||
MessageBox(NULL, L"Release of DC and RC failed.", L"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
|
||||
|
@ -458,6 +460,14 @@ void WindowsGLContext::ShutdownFromRenderThread() {
|
|||
hWnd_ = NULL;
|
||||
}
|
||||
|
||||
void WindowsGLContext::ShutdownFromRenderThread() {
|
||||
delete draw_;
|
||||
draw_ = nullptr;
|
||||
CloseHandle(pauseEvent);
|
||||
CloseHandle(resumeEvent);
|
||||
ReleaseGLContext();
|
||||
}
|
||||
|
||||
void WindowsGLContext::Resize() {
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ public:
|
|||
Draw::DrawContext *GetDrawContext() override { return draw_; }
|
||||
|
||||
private:
|
||||
void ReleaseGLContext();
|
||||
|
||||
bool renderThread_;
|
||||
Draw::DrawContext *draw_;
|
||||
GLRenderManager *renderManager_;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "base/display.h"
|
||||
#include "base/NativeApp.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
|
@ -17,12 +18,11 @@ bool AndroidJavaEGLGraphicsContext::InitFromRenderThread(ANativeWindow *wnd, int
|
|||
// OpenGL handles rotated rendering in the driver.
|
||||
g_display_rotation = DisplayRotation::ROTATE_0;
|
||||
g_display_rot_matrix.setIdentity();
|
||||
draw_ = Draw::T3DCreateGLContext();
|
||||
draw_ = Draw::T3DCreateGLContext(); // Can't fail
|
||||
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
renderManager_->SetInflightFrames(g_Config.iInflightFrames);
|
||||
bool success = draw_->CreatePresets();
|
||||
_assert_msg_(success, "Failed to compile preset shaders");
|
||||
return success;
|
||||
draw_->CreatePresets();
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndroidJavaEGLGraphicsContext::ShutdownFromRenderThread() {
|
||||
|
|
|
@ -71,7 +71,6 @@ bool AndroidVulkanContext::InitAPI() {
|
|||
}
|
||||
|
||||
g_Vulkan->ChooseDevice(physicalDevice);
|
||||
// Here we can enable device extensions if we like.
|
||||
|
||||
ILOG("Creating Vulkan device");
|
||||
if (g_Vulkan->CreateDevice() != VK_SUCCESS) {
|
||||
|
@ -82,6 +81,7 @@ bool AndroidVulkanContext::InitAPI() {
|
|||
g_Vulkan = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
ILOG("Vulkan device created!");
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// It calls a set of methods defined in NativeApp.h. These should be implemented
|
||||
// by your game or app.
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
|
||||
|
@ -594,7 +593,6 @@ retry:
|
|||
ELOG("NativeApp.init(): iGPUBackend %d not supported. Switching to OpenGL.", (int)g_Config.iGPUBackend);
|
||||
g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
|
||||
goto retry;
|
||||
// Crash();
|
||||
}
|
||||
|
||||
if (useCPUThread) {
|
||||
|
@ -688,7 +686,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) {
|
|||
}
|
||||
|
||||
// JavaEGL
|
||||
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, jobject obj) {
|
||||
extern "C" bool Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, jobject obj) {
|
||||
// We should be running on the render thread here.
|
||||
std::string errorMessage;
|
||||
if (renderer_inited) {
|
||||
|
@ -712,21 +710,34 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env,
|
|||
|
||||
ILOG("Shut down both threads. Now let's bring it up again!");
|
||||
|
||||
graphicsContext->InitFromRenderThread(nullptr, 0, 0, 0, 0);
|
||||
if (!graphicsContext->InitFromRenderThread(nullptr, 0, 0, 0, 0)) {
|
||||
SystemToast("Graphics initialization failed. Quitting.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (useCPUThread) {
|
||||
EmuThreadStart();
|
||||
} else {
|
||||
NativeInitGraphics(graphicsContext);
|
||||
if (!NativeInitGraphics(graphicsContext)) {
|
||||
// Gonna be in a weird state here, not good.
|
||||
SystemToast("Failed to initialize graphics.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
graphicsContext->ThreadStart();
|
||||
ILOG("Restored.");
|
||||
} else {
|
||||
ILOG("NativeApp.displayInit() first time");
|
||||
graphicsContext->InitFromRenderThread(nullptr, 0, 0, 0, 0);
|
||||
if (!graphicsContext->InitFromRenderThread(nullptr, 0, 0, 0, 0)) {
|
||||
SystemToast("Graphics initialization failed. Quitting.");
|
||||
return false;
|
||||
}
|
||||
graphicsContext->ThreadStart();
|
||||
renderer_inited = true;
|
||||
}
|
||||
NativeMessageReceived("recreateviews", "");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void recalculateDpi() {
|
||||
|
@ -1156,6 +1167,11 @@ static void ProcessFrameCommands(JNIEnv *env) {
|
|||
}
|
||||
|
||||
extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(JNIEnv *env, jobject obj, jobject _surf) {
|
||||
if (!graphicsContext) {
|
||||
ELOG("runEGLRenderLoop: Tried to enter without a created graphics context.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Needed for Vulkan, even if we're not using the old EGL path.
|
||||
|
||||
exitRenderLoop = false;
|
||||
|
@ -1175,10 +1191,11 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J
|
|||
auto tryInit = [&]() {
|
||||
if (graphicsContext->InitFromRenderThread(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY, backbuffer_format, androidVersion)) {
|
||||
return true;
|
||||
} else {
|
||||
ELOG("Failed to initialize graphics context.");
|
||||
SystemToast("Failed to initialize graphics context.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ELOG("Failed to initialize graphics context.");
|
||||
return false;
|
||||
};
|
||||
|
||||
bool initSuccess = tryInit();
|
||||
|
@ -1202,7 +1219,10 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J
|
|||
|
||||
if (!exitRenderLoop) {
|
||||
if (!useCPUThread) {
|
||||
NativeInitGraphics(graphicsContext);
|
||||
if (!NativeInitGraphics(graphicsContext)) {
|
||||
ELOG("Failed to initialize graphics.");
|
||||
// Gonna be in a weird state here..
|
||||
}
|
||||
}
|
||||
graphicsContext->ThreadStart();
|
||||
renderer_inited = true;
|
||||
|
|
|
@ -616,6 +616,7 @@ public abstract class NativeActivity extends Activity {
|
|||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
Log.i(TAG, "onDestroy");
|
||||
if (javaGL) {
|
||||
if (nativeRenderer.isRenderingFrame()) {
|
||||
Log.i(TAG, "Waiting for renderer to finish.");
|
||||
|
@ -628,7 +629,6 @@ public abstract class NativeActivity extends Activity {
|
|||
tries--;
|
||||
} while (nativeRenderer.isRenderingFrame() && tries > 0);
|
||||
}
|
||||
Log.i(TAG, "onDestroy");
|
||||
mGLSurfaceView.onDestroy();
|
||||
mGLSurfaceView = null;
|
||||
} else {
|
||||
|
|
|
@ -13,6 +13,7 @@ public class NativeRenderer implements GLSurfaceView.Renderer {
|
|||
private static String TAG = "NativeRenderer";
|
||||
private NativeActivity mActivity;
|
||||
private boolean inFrame;
|
||||
private boolean failed = false;
|
||||
|
||||
NativeRenderer(NativeActivity act) {
|
||||
mActivity = act;
|
||||
|
@ -21,6 +22,7 @@ public class NativeRenderer implements GLSurfaceView.Renderer {
|
|||
public boolean isRenderingFrame() {
|
||||
return inFrame;
|
||||
}
|
||||
public boolean hasFailedInit() { return failed; }
|
||||
|
||||
public void onDrawFrame(GL10 unused /*use GLES20*/) {
|
||||
inFrame = true;
|
||||
|
@ -29,6 +31,7 @@ public class NativeRenderer implements GLSurfaceView.Renderer {
|
|||
}
|
||||
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
failed = false;
|
||||
Log.i(TAG, "NativeRenderer: onSurfaceCreated");
|
||||
|
||||
EGL10 egl = (EGL10)EGLContext.getEGL();
|
||||
|
@ -49,7 +52,10 @@ public class NativeRenderer implements GLSurfaceView.Renderer {
|
|||
}
|
||||
// Log.i(TAG, "onSurfaceCreated - EGL context is new or was lost");
|
||||
// Actually, it seems that it is here we should recreate lost GL objects.
|
||||
displayInit();
|
||||
if (!displayInit()) {
|
||||
Log.e(TAG, "Display init failed");
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void onSurfaceChanged(GL10 unused, int width, int height) {
|
||||
|
@ -57,7 +63,7 @@ public class NativeRenderer implements GLSurfaceView.Renderer {
|
|||
|
||||
// Note: This also means "device lost" and you should reload
|
||||
// all buffered objects.
|
||||
public native void displayInit();
|
||||
public native boolean displayInit();
|
||||
|
||||
public native void displayRender();
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "math/dataconv.h"
|
||||
|
|
Loading…
Add table
Reference in a new issue