Merge pull request #10366 from hrydgard/gl-lost-device-rework

Rework GL lost-device to work more like Vulkan. Gets rid of gl_lost manager etc.
This commit is contained in:
Henrik Rydgård 2017-12-07 22:48:43 +01:00 committed by GitHub
commit 3eda310009
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 90 additions and 465 deletions

View file

@ -868,8 +868,6 @@ add_library(native STATIC
ext/native/gfx/gl_common.h
ext/native/gfx/gl_debug_log.cpp
ext/native/gfx/gl_debug_log.h
ext/native/gfx/gl_lost_manager.cpp
ext/native/gfx/gl_lost_manager.h
ext/native/gfx/texture_atlas.cpp
ext/native/gfx/texture_atlas.h
ext/native/gfx/d3d9_shader.cpp

View file

@ -132,7 +132,6 @@ DrawEngineGLES::DrawEngineGLES() : vai_(256) {
indexGen.Setup(decIndex);
InitDeviceObjects();
register_gl_resource_holder(this, "drawengine_gles", 1);
tessDataTransfer = new TessellationDataTransferGLES(gl_extensions.VersionGEThan(3, 0, 0));
}
@ -143,8 +142,6 @@ DrawEngineGLES::~DrawEngineGLES() {
FreeMemoryPages(decIndex, DECODED_INDEX_BUFFER_SIZE);
FreeMemoryPages(splineBuffer, SPLINE_BUFFER_SIZE);
unregister_gl_resource_holder(this);
delete tessDataTransfer;
}
@ -191,21 +188,6 @@ void DrawEngineGLES::DestroyDeviceObjects() {
}
}
void DrawEngineGLES::GLLost() {
ILOG("TransformDrawEngine::GLLost()");
// The objects have already been deleted by losing the context, so we don't call DestroyDeviceObjects.
bufferNameCache_.clear();
bufferNameInfo_.clear();
freeSizedBuffers_.clear();
bufferNameCacheSize_ = 0;
ClearTrackedVertexArrays();
}
void DrawEngineGLES::GLRestore() {
ILOG("TransformDrawEngine::GLRestore()");
InitDeviceObjects();
}
struct GlTypeInfo {
u16 type;
u8 count;

View file

@ -28,7 +28,6 @@
#include "GPU/Common/GPUStateUtils.h"
#include "GPU/GLES/FragmentShaderGeneratorGLES.h"
#include "gfx/gl_common.h"
#include "gfx/gl_lost_manager.h"
class LinkedShader;
class ShaderManagerGLES;
@ -100,7 +99,7 @@ public:
};
// Handles transform, lighting and drawing.
class DrawEngineGLES : public DrawEngineCommon, public GfxResourceHolder {
class DrawEngineGLES : public DrawEngineCommon {
public:
DrawEngineGLES();
virtual ~DrawEngineGLES();
@ -122,8 +121,6 @@ public:
void RestoreVAO();
void InitDeviceObjects();
void DestroyDeviceObjects();
void GLLost() override;
void GLRestore() override;
void ClearTrackedVertexArrays() override;
void DecimateTrackedVertexArrays();

View file

@ -75,6 +75,8 @@ static const char basic_vs[] =
" gl_Position = a_position;\n"
"}\n";
const int MAX_PBO = 2;
void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format);
void FramebufferManagerGLES::DisableState() {
@ -189,25 +191,11 @@ void FramebufferManagerGLES::BindPostShader(const PostShaderUniforms &uniforms)
glUniform1f(videoLoc_, uniforms.video);
}
void FramebufferManagerGLES::DestroyDraw2DProgram() {
if (draw2dprogram_) {
glsl_destroy(draw2dprogram_);
draw2dprogram_ = nullptr;
}
if (postShaderProgram_) {
glsl_destroy(postShaderProgram_);
postShaderProgram_ = nullptr;
}
}
FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) :
FramebufferManagerCommon(draw),
drawPixelsTex_(0),
drawPixelsTexFormat_(GE_FORMAT_INVALID),
convBuf_(nullptr),
draw2dprogram_(nullptr),
postShaderProgram_(nullptr),
stencilUploadProgram_(nullptr),
videoLoc_(-1),
timeLoc_(-1),
pixelDeltaLoc_(-1),
@ -219,6 +207,7 @@ FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) :
{
needBackBufferYSwap_ = true;
needGLESRebinds_ = true;
CreateDeviceObjects();
}
void FramebufferManagerGLES::Init() {
@ -243,19 +232,38 @@ void FramebufferManagerGLES::SetDrawEngine(DrawEngineGLES *td) {
drawEngine_ = td;
}
FramebufferManagerGLES::~FramebufferManagerGLES() {
if (drawPixelsTex_)
void FramebufferManagerGLES::CreateDeviceObjects() {
CompileDraw2DProgram();
}
void FramebufferManagerGLES::DestroyDeviceObjects() {
if (draw2dprogram_) {
glsl_destroy(draw2dprogram_);
draw2dprogram_ = nullptr;
}
if (postShaderProgram_) {
glsl_destroy(postShaderProgram_);
postShaderProgram_ = nullptr;
}
if (drawPixelsTex_) {
glDeleteTextures(1, &drawPixelsTex_);
DestroyDraw2DProgram();
drawPixelsTex_ = 0;
}
if (stencilUploadProgram_) {
glsl_destroy(stencilUploadProgram_);
stencilUploadProgram_ = nullptr;
}
}
for (auto it = tempFBOs_.begin(), end = tempFBOs_.end(); it != end; ++it) {
it->second.fbo->Release();
FramebufferManagerGLES::~FramebufferManagerGLES() {
DestroyDeviceObjects();
if (pixelBufObj_) {
for (int i = 0; i < MAX_PBO; i++) {
glDeleteBuffers(1, &pixelBufObj_[i].handle);
}
delete[] pixelBufObj_;
}
delete [] pixelBufObj_;
delete [] convBuf_;
}
@ -761,7 +769,6 @@ void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u
void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) {
CHECK_GL_ERROR_IF_DEBUG();
const int MAX_PBO = 2;
GLubyte *packed = 0;
bool unbind = false;
const u8 nextPBO = (currentPBO_ + 1) % MAX_PBO;
@ -1005,7 +1012,12 @@ void FramebufferManagerGLES::EndFrame() {
void FramebufferManagerGLES::DeviceLost() {
DestroyAllFBOs();
DestroyDraw2DProgram();
DestroyDeviceObjects();
}
void FramebufferManagerGLES::DeviceRestore(Draw::DrawContext *draw) {
draw_ = draw;
CreateDeviceObjects();
}
void FramebufferManagerGLES::DestroyAllFBOs() {
@ -1046,8 +1058,6 @@ void FramebufferManagerGLES::Resized() {
DestroyAllFBOs();
}
DestroyDraw2DProgram();
#ifndef USING_GLES2
if (g_Config.iInternalResolution == 0) {
glLineWidth(std::max(1, (int)(renderWidth_ / 480)));
@ -1057,10 +1067,6 @@ void FramebufferManagerGLES::Resized() {
glPointSize((float)g_Config.iInternalResolution);
}
#endif
if (!draw2dprogram_) {
CompileDraw2DProgram();
}
}
bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) {

View file

@ -83,6 +83,8 @@ public:
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
virtual void RebindFramebuffer() override;
void DeviceRestore(Draw::DrawContext *draw);
protected:
void SetViewport2D(int x, int y, int w, int h) override;
void DisableState() override;
@ -94,6 +96,9 @@ protected:
void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
private:
void CreateDeviceObjects();
void DestroyDeviceObjects();
void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) override;
void Bind2DShader() override;
void BindPostShader(const PostShaderUniforms &uniforms) override;
@ -113,10 +118,9 @@ private:
u8 *convBuf_;
u32 convBufSize_;
GLSLProgram *draw2dprogram_;
GLSLProgram *plainColorProgram_;
GLSLProgram *postShaderProgram_;
GLSLProgram *stencilUploadProgram_;
GLSLProgram *draw2dprogram_ = nullptr;
GLSLProgram *postShaderProgram_ = nullptr;
GLSLProgram *stencilUploadProgram_ = nullptr;
int plainColorLoc_;
int videoLoc_;
int timeLoc_;

View file

@ -385,23 +385,24 @@ void GPU_GLES::BuildReportingInfo() {
void GPU_GLES::DeviceLost() {
ILOG("GPU_GLES: DeviceLost");
// Should only be executed on the GL thread.
// Simply drop all caches and textures.
// FBOs appear to survive? Or no?
// TransformDraw has registered as a GfxResourceHolder.
shaderManagerGL_->ClearCache(false);
textureCacheGL_->Clear(false);
fragmentTestCache_.Clear(false);
depalShaderCache_.Clear();
drawEngine_.ClearTrackedVertexArrays();
framebufferManagerGL_->DeviceLost();
}
void GPU_GLES::DeviceRestore() {
draw_ = (Draw::DrawContext *)PSP_CoreParameter().graphicsContext->GetDrawContext();
ILOG("GPU_GLES: DeviceRestore");
UpdateCmdInfo();
UpdateVsyncInterval(true);
textureCacheGL_->DeviceRestore(draw_);
framebufferManagerGL_->DeviceRestore(draw_);
}
void GPU_GLES::Reinitialize() {

View file

@ -917,6 +917,11 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, w, h, components2, dstFmt, pixelData);
} else {
PROFILE_THIS_SCOPE("loadtex");
// Avoid misleading errors in texture upload, these are common.
GLenum err = glGetError();
if (err) {
WARN_LOG(G3D, "Got an error BEFORE texture upload: %08x (%s)", err, GLEnumToString(err).c_str());
}
if (IsFakeMipmapChange())
glTexImage2D(GL_TEXTURE_2D, 0, components, w, h, 0, components2, dstFmt, pixelData);
else
@ -925,7 +930,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
// TODO: We really, really should avoid calling glGetError.
GLenum err = glGetError();
if (err == GL_OUT_OF_MEMORY) {
WARN_LOG_REPORT(G3D, "Texture cache ran out of GPU memory; switching to low memory mode");
WARN_LOG(G3D, "Texture cache ran out of GPU memory; switching to low memory mode");
lowMemoryMode_ = true;
decimationCounter_ = 0;
Decimate();
@ -939,15 +944,9 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
host->NotifyUserMessage(err->T("Warning: Video memory FULL, switching to slow caching mode"), 2.0f);
}
} else if (err != GL_NO_ERROR) {
const char *str = "other";
switch (err) {
case GL_OUT_OF_MEMORY: str = "out_of_memory"; break;
case GL_INVALID_ENUM: str = "invalid_enum"; break;
case GL_INVALID_VALUE: str = "invalid_value"; break;
}
// We checked the err anyway, might as well log if there is one.
WARN_LOG(G3D, "Got an error in texture upload: %08x (%s) (components=%s components2=%s dstFmt=%s w=%d h=%d level=%d)",
err, str, GLEnumToString(components).c_str(), GLEnumToString(components2).c_str(), GLEnumToString(dstFmt).c_str(),
err, GLEnumToString(err).c_str(), GLEnumToString(components).c_str(), GLEnumToString(components2).c_str(), GLEnumToString(dstFmt).c_str(),
w, h, level);
}
}
@ -1066,3 +1065,7 @@ bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level)
return false;
#endif
}
void TextureCacheGLES::DeviceRestore(Draw::DrawContext *draw) {
draw_ = draw;
}

View file

@ -69,6 +69,8 @@ public:
void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight);
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
void DeviceRestore(Draw::DrawContext *draw);
protected:
void BindTexture(TexCacheEntry *entry) override;
void Unbind() override;

View file

@ -1,7 +1,6 @@
#include "debugger_memorytex.h"
#include "gfx/GLStateCache.h"
#include "gfx/gl_common.h"
#include "gfx/gl_lost_manager.h"
#include "ui_debugger_memorytex.h"
#include "Core/MemMap.h"
#include <QImage>

View file

@ -1163,24 +1163,6 @@ void EmuScreen::renderUI() {
screenManager()->getUIContext()->End();
}
void EmuScreen::deviceLost() {
ILOG("EmuScreen::deviceLost()");
if (gpu)
gpu->DeviceLost();
else
ILOG("No gpu to deviceLost!");
}
void EmuScreen::deviceRestore() {
ILOG("EmuScreen::deviceRestore()");
if (gpu)
gpu->DeviceRestore();
else
ILOG("No gpu to deviceRestore!");
RecreateViews();
}
void EmuScreen::autoLoad() {
//check if save state has save, if so, load
int lastSlot = SaveState::GetNewestSlot(gamePath_);

View file

@ -40,8 +40,6 @@ public:
void render() override;
void preRender() override;
void postRender() override;
void deviceLost() override;
void deviceRestore() override;
void dialogFinished(const Screen *dialog, DialogResult result) override;
void sendMessage(const char *msg, const char *value) override;
void resized() override;

View file

@ -52,7 +52,6 @@
#include "net/resolve.h"
#include "gfx_es2/draw_text.h"
#include "gfx_es2/gpu_features.h"
#include "gfx/gl_lost_manager.h"
#include "i18n/i18n.h"
#include "input/input_state.h"
#include "math/fast/fast_math.h"
@ -559,9 +558,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
// We do this here, instead of in NativeInitGraphics, because the display may be reset.
// When it's reset we don't want to forget all our managed things.
SetGPUBackend((GPUBackend) g_Config.iGPUBackend);
if (GetGPUBackend() == GPUBackend::OPENGL) {
gl_lost_manager_init();
}
// Must be done restarting by now.
restarting = false;
@ -694,12 +690,18 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) {
g_gameInfoCache = new GameInfoCache();
if (gpu)
gpu->DeviceRestore();
g_graphicsInited = true;
ILOG("NativeInitGraphics completed");
return true;
}
void NativeShutdownGraphics() {
if (gpu)
gpu->DeviceLost();
g_graphicsInited = false;
ILOG("NativeShutdownGraphics");
@ -860,15 +862,17 @@ void NativeRender(GraphicsContext *graphicsContext) {
#endif
}
// Test lost/restore on PC
#if 0
if (gpu) {
gpu->DeviceLost();
gpu->DeviceRestore();
}
#endif
graphicsContext->Resize();
screenManager->resized();
// Do not enable unless you are testing device-loss on Windows
#if 0
screenManager->deviceLost();
screenManager->deviceRestore();
#endif
// TODO: Move this to new GraphicsContext objects for each backend.
#ifndef _WIN32
if (GetGPUBackend() == GPUBackend::OPENGL) {
@ -951,26 +955,6 @@ void NativeUpdate() {
screenManager->update();
}
void NativeDeviceLost() {
ILOG("NativeDeviceLost");
// We start by calling gl_lost - this lets objects zero their native GL objects
// so they then don't try to delete them as well.
if (GetGPUBackend() == GPUBackend::OPENGL) {
gl_lost();
}
if (g_gameInfoCache)
g_gameInfoCache->Clear();
screenManager->deviceLost();
}
void NativeDeviceRestore() {
ILOG("NativeDeviceRestore");
if (GetGPUBackend() == GPUBackend::OPENGL) {
gl_restore();
}
screenManager->deviceRestore();
}
bool NativeIsAtTopLevel() {
Screen *currentScreen = screenManager->topScreen();
if (currentScreen) {
@ -1127,9 +1111,6 @@ void NativeShutdown() {
screenManager = nullptr;
host->ShutdownGraphics();
if (GetGPUBackend() == GPUBackend::OPENGL) {
gl_lost_manager_shutdown();
}
#if !PPSSPP_PLATFORM(UWP)
delete host;

View file

@ -4,7 +4,6 @@
#include "thin3d/thin3d.h"
#include "Core/Config.h"
#include "gfx/gl_lost_manager.h"
enum ImageFileType {
PNG,
@ -14,36 +13,14 @@ enum ImageFileType {
TYPE_UNKNOWN,
};
class ManagedTexture : public GfxResourceHolder {
class ManagedTexture {
public:
ManagedTexture(Draw::DrawContext *draw) : draw_(draw) {
if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL)
register_gl_resource_holder(this, "managed_texture", 0);
}
~ManagedTexture() {
if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL)
unregister_gl_resource_holder(this);
if (texture_)
texture_->Release();
}
void GLLost() override {
if (texture_)
texture_->Release();
texture_ = nullptr;
}
void GLRestore() override {
if (!filename_.empty()) {
if (LoadFromFile(filename_.c_str())) {
ILOG("Reloaded lost texture %s", filename_.c_str());
}
else {
ELOG("Failed to reload lost texture %s", filename_.c_str());
}
}
else {
WLOG("Texture cannot be restored - has no filename");
}
}
bool LoadFromFile(const std::string &filename, ImageFileType type = ImageFileType::DETECT, bool generateMips = false);
bool LoadFromFileData(const uint8_t *data, size_t dataSize, ImageFileType type = ImageFileType::DETECT, bool generateMips = false);

View file

@ -437,7 +437,6 @@ static float dp_xscale = 1.0f;
static float dp_yscale = 1.0f;
static bool renderer_inited = false;
static bool renderer_ever_inited = false;
static bool sustainedPerfSupported = false;
// See NativeQueryConfig("androidJavaGL") to change this value.
@ -609,7 +608,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init
PROFILE_INIT();
renderer_inited = false;
renderer_ever_inited = false;
androidVersion = jAndroidVersion;
deviceType = jdeviceType;
@ -748,16 +746,16 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env,
if (renderer_inited) {
ILOG("NativeApp.displayInit() restoring");
NativeDeviceLost();
NativeShutdownGraphics();
NativeDeviceRestore();
delete graphicsContext;
graphicsContext = new AndroidJavaEGLGraphicsContext();
NativeInitGraphics(graphicsContext);
ILOG("Restored.");
} else {
ILOG("NativeApp.displayInit() first time");
NativeInitGraphics(graphicsContext);
renderer_inited = true;
renderer_ever_inited = true;
}
NativeMessageReceived("recreateviews", "");
@ -1150,13 +1148,9 @@ retry:
return false;
}
if (!exitRenderLoop && !renderer_inited) {
if (!exitRenderLoop) {
NativeInitGraphics(graphicsContext);
if (renderer_ever_inited) {
NativeDeviceRestore();
}
renderer_inited = true;
renderer_ever_inited = true;
}
while (!exitRenderLoop) {
@ -1180,8 +1174,7 @@ retry:
if (g_gameInfoCache)
g_gameInfoCache->WorkQueue()->Flush();
if (renderer_inited)
NativeDeviceLost();
NativeShutdownGraphics();
renderer_inited = false;
ILOG("Shutting down graphics context.");

View file

@ -77,7 +77,6 @@ LOCAL_SRC_FILES :=\
gfx_es2/draw_text_android.cpp.arm \
gfx/GLStateCache.cpp.arm \
gfx/gl_debug_log.cpp \
gfx/gl_lost_manager.cpp \
gfx/texture_atlas.cpp \
image/zim_load.cpp \
image/zim_save.cpp \

View file

@ -51,13 +51,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
// Should not initialize anything screen-size-dependent - do that in NativeResized.
bool NativeInitGraphics(GraphicsContext *graphicsContext);
// Signals that you need to forget all buffered OpenGL resources,
// like textures, vbo etc.
void NativeDeviceLost();
// Signals that it's time to recreate buffered OpenGL resources
void NativeDeviceRestore();
// If you want to change DPI stuff (such as modifying dp_xres and dp_yres), this is the
// place to do it. You should only read g_dpi_scale and pixel_xres and pixel_yres in this,
// and only write dp_xres and dp_yres.

View file

@ -1,131 +0,0 @@
#include <vector>
#include <mutex>
#include "base/basictypes.h"
#include "base/logging.h"
#include "gfx/gl_lost_manager.h"
struct Holder {
GfxResourceHolder *holder;
const char *desc;
int priority;
};
static std::mutex mutex;
std::vector<Holder> *holders;
static bool inLost;
static bool inRestore;
static int g_max_priority = 0;
void register_gl_resource_holder(GfxResourceHolder *holder, const char *desc, int priority) {
std::lock_guard<std::mutex> lock(mutex);
if (inLost || inRestore) {
FLOG("BAD: Should not call register_gl_resource_holder from lost/restore path");
return;
}
if (holders) {
holders->push_back({ holder, desc, priority });
if (g_max_priority < priority)
g_max_priority = priority;
} else {
WLOG("GL resource holder not initialized, cannot register resource");
}
}
void unregister_gl_resource_holder(GfxResourceHolder *holder) {
std::lock_guard<std::mutex> lock(mutex);
if (inLost || inRestore) {
FLOG("BAD: Should not call unregister_gl_resource_holder from lost/restore path");
return;
}
if (holders) {
bool erased = false;
for (size_t i = 0; i < holders->size(); i++) {
if ((*holders)[i].holder == holder) {
if (erased) {
ELOG("GL object double-registered!");
}
holders->erase(holders->begin() + i);
erased = true;
}
}
if (!erased) {
WLOG("unregister_gl_resource_holder: Resource not registered");
}
} else {
WLOG("GL resource holder not initialized or already shutdown, cannot unregister resource");
}
}
void gl_restore() {
std::lock_guard<std::mutex> lock(mutex);
inRestore = true;
if (!holders) {
WLOG("GL resource holder not initialized, cannot process restore request");
inRestore = false;
return;
}
ILOG("gl_restore() restoring %d items:", (int)holders->size());
for (int p = 0; p <= g_max_priority; p++) {
for (size_t i = 0; i < holders->size(); i++) {
if ((*holders)[i].priority == p) {
ILOG("GLRestore(%d / %d, %s, prio %d)", (int)(i + 1), (int)holders->size(),
(*holders)[i].desc, (*holders)[i].priority);
(*holders)[i].holder->GLRestore();
}
}
}
ILOG("gl_restore() completed on %d items:", (int)holders->size());
inRestore = false;
}
void gl_lost() {
std::lock_guard<std::mutex> lock(mutex);
inLost = true;
if (!holders) {
WLOG("GL resource holder not initialized, cannot process restore request");
inLost = false;
return;
}
ILOG("gl_lost() clearing %i items:", (int)holders->size());
for (int p = g_max_priority; p >= 0; p--) {
for (size_t i = 0; i < holders->size(); i++) {
if ((*holders)[i].priority == p) {
ILOG("gl_lost(%d / %d, %s, prio %d)", (int) (i + 1), (int) holders->size(),
(*holders)[i].desc, (*holders)[i].priority);
(*holders)[i].holder->GLLost();
}
}
}
ILOG("gl_lost() completed on %i items:", (int)holders->size());
inLost = false;
}
void gl_lost_manager_init() {
std::lock_guard<std::mutex> lock(mutex);
if (holders) {
FLOG("Double GL lost manager init");
// Dead here (FLOG), no need to delete holders
}
g_max_priority = 0;
holders = new std::vector<Holder>();
}
void gl_lost_manager_shutdown() {
std::lock_guard<std::mutex> lock(mutex);
if (!holders) {
FLOG("Lost manager already shutdown");
} else if (holders->size() > 0) {
ELOG("Lost manager shutdown with %i objects still registered", (int)holders->size());
for (size_t i = 0; i < holders->size(); i++) {
ELOG(" (%d / %d, %s, prio %d)", (int)(i + 1), (int)holders->size(),
(*holders)[i].desc, (*holders)[i].priority);
}
}
delete holders;
holders = 0;
}

View file

@ -1,36 +0,0 @@
#pragma once
// On Android, even OpenGL can lose allocated resources. This is a utility to keep
// track of them.
// It's important to realize that with OpenGL, there's no Lost event that can be relied upon.
// The only solid indication we get is onSurfaceCreated. That is called every time the graphics
// surface that we render upon has been recreated. When that's called, we know that any
// gl resources we owned before it was called have been killed and need to be recreated.
// However, with D3D UWP, and potentially other platforms, there is a lost event.
// So we keep that infrastructure, but with GL we simply call both Lost and Restore when we detect a Restore.
// For code simplicity, it may be a good idea to manually tear down and recreate everything. Even in this case,
// it's important to use this to zero out resource handles in GLLost() - gl_lost should be called before you
// tear things down, so then you can check if handles are zero and avoid deleting resources that are already gone.
class GfxResourceHolder {
public:
virtual ~GfxResourceHolder() {}
virtual void GLLost() = 0;
virtual void GLRestore() = 0;
};
void gl_lost_manager_init();
void gl_lost_manager_shutdown();
// The string pointed to by desc must be a constant or otherwise live for the entire registered lifetime of the object.
void register_gl_resource_holder(GfxResourceHolder *holder, const char *desc, int priority);
void unregister_gl_resource_holder(GfxResourceHolder *holder);
// Notifies all objects it's time to forget / delete things.
void gl_lost();
// Notifies all objects that it's time to be restored.
void gl_restore();

View file

@ -6,7 +6,6 @@
#include "base/basictypes.h"
#include "base/colorutil.h"
#include "gfx/gl_lost_manager.h"
#include "gfx/texture_atlas.h"
#include "math/geom2d.h"
#include "math/lin/matrix4x4.h"

View file

@ -49,7 +49,6 @@ GLSLProgram *glsl_create(const char *vshader, const char *fshader, std::string *
delete program;
return 0;
}
register_gl_resource_holder(program, "glsl_program", 0);
return program;
}
@ -70,7 +69,6 @@ GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src
delete program;
return 0;
}
register_gl_resource_holder(program, "glsl_program_src", 0);
return program;
}
@ -220,23 +218,6 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) {
return true;
}
void GLSLProgram::GLLost() {
// Quoth http://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html:
// "Note that when the EGL context is lost, all OpenGL resources associated with that context will be automatically deleted.
// You do not need to call the corresponding "glDelete" methods such as glDeleteTextures to manually delete these lost resources."
program_ = 0;
vsh_ = 0;
fsh_ = 0;
}
void GLSLProgram::GLRestore() {
ILOG("Restoring GLSL program %s/%s",
strlen(this->vshader_filename) > 0 ? this->vshader_filename : "(mem)",
strlen(this->fshader_filename) > 0 ? this->fshader_filename : "(mem)");
glsl_recompile(this);
// Note that any shader uniforms are still lost, hopefully the client sets them every frame at a minimum...
}
int glsl_attrib_loc(const GLSLProgram *program, const char *name) {
return glGetAttribLocation(program->program_, name);
}
@ -247,7 +228,6 @@ int glsl_uniform_loc(const GLSLProgram *program, const char *name) {
void glsl_destroy(GLSLProgram *program) {
if (program) {
unregister_gl_resource_holder(program);
glDeleteShader(program->vsh_);
glDeleteShader(program->fsh_);
glDeleteProgram(program->program_);

View file

@ -7,13 +7,12 @@
#include <string>
#include <time.h>
#include "gfx/gl_lost_manager.h"
#include "gfx/gl_common.h"
// Represent a compiled and linked vshader/fshader pair.
// A just-constructed object is valid but cannot be used as a shader program, meaning that
// yes, you can declare these as globals if you like.
struct GLSLProgram : public GfxResourceHolder {
struct GLSLProgram {
char name[16];
char vshader_filename[256];
char fshader_filename[256];
@ -42,9 +41,6 @@ struct GLSLProgram : public GfxResourceHolder {
GLuint vsh_;
GLuint fsh_;
GLuint program_;
void GLLost() override;
void GLRestore() override;
};
// C API, old skool. Not much point either...

View file

@ -234,7 +234,6 @@
<ClInclude Include="gfx\GLStateCache.h" />
<ClInclude Include="gfx\gl_common.h" />
<ClInclude Include="gfx\gl_debug_log.h" />
<ClInclude Include="gfx\gl_lost_manager.h" />
<ClInclude Include="gfx\texture_atlas.h" />
<ClInclude Include="gfx_es2\draw_text_android.h" />
<ClInclude Include="gfx_es2\draw_text_qt.h" />
@ -693,7 +692,6 @@
<ClCompile Include="gfx\d3d9_state.cpp" />
<ClCompile Include="gfx\GLStateCache.cpp" />
<ClCompile Include="gfx\gl_debug_log.cpp" />
<ClCompile Include="gfx\gl_lost_manager.cpp" />
<ClCompile Include="gfx\texture_atlas.cpp" />
<ClCompile Include="gfx_es2\draw_text_android.cpp" />
<ClCompile Include="gfx_es2\draw_text_qt.cpp" />

View file

@ -74,9 +74,6 @@
<ClInclude Include="base\basictypes.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="gfx\gl_lost_manager.h">
<Filter>gfx</Filter>
</ClInclude>
<ClInclude Include="gfx\texture_atlas.h">
<Filter>gfx</Filter>
</ClInclude>
@ -370,9 +367,6 @@
<ClCompile Include="file\zip_read.cpp">
<Filter>file</Filter>
</ClCompile>
<ClCompile Include="gfx\gl_lost_manager.cpp">
<Filter>gfx</Filter>
</ClCompile>
<ClCompile Include="gfx\texture_atlas.cpp">
<Filter>gfx</Filter>
</ClCompile>

View file

@ -13,7 +13,6 @@
#include "gfx/gl_debug_log.h"
#include "gfx/GLStateCache.h"
#include "gfx_es2/gpu_features.h"
#include "gfx/gl_lost_manager.h"
#ifdef IOS
extern void bindDefaultFBO();
@ -274,11 +273,10 @@ GLuint ShaderStageToOpenGL(ShaderStage stage) {
}
}
class OpenGLShaderModule : public ShaderModule, public GfxResourceHolder {
class OpenGLShaderModule : public ShaderModule {
public:
OpenGLShaderModule(ShaderStage stage) : stage_(stage) {
ILOG("Shader module created (%p)", this);
register_gl_resource_holder(this, "drawcontext_shader_module", 0);
glstage_ = ShaderStageToOpenGL(stage);
}
@ -286,7 +284,6 @@ public:
ILOG("Shader module destroyed (%p)", this);
if (shader_)
glDeleteShader(shader_);
unregister_gl_resource_holder(this);
}
bool Compile(ShaderLanguage language, const uint8_t *data, size_t dataSize);
@ -302,19 +299,6 @@ public:
return stage_;
}
void GLLost() override {
ILOG("Shader module lost");
// Shader has been destroyed since the old context is gone, so let's zero it.
shader_ = 0;
}
void GLRestore() override {
ILOG("Shader module being restored");
if (!Compile(language_, (const uint8_t *)source_.data(), source_.size())) {
ELOG("Shader restore compilation failed: %s", source_.c_str());
}
}
private:
ShaderStage stage_;
ShaderLanguage language_;
@ -355,15 +339,13 @@ bool OpenGLShaderModule::Compile(ShaderLanguage language, const uint8_t *data, s
return ok_;
}
class OpenGLInputLayout : public InputLayout, GfxResourceHolder {
class OpenGLInputLayout : public InputLayout {
public:
~OpenGLInputLayout();
void Apply(const void *base = nullptr);
void Unapply();
void Compile();
void GLRestore() override;
void GLLost() override;
bool RequiresBuffer() {
return id_ != 0;
}
@ -381,15 +363,12 @@ struct UniformInfo {
int loc_;
};
class OpenGLPipeline : public Pipeline, GfxResourceHolder {
class OpenGLPipeline : public Pipeline {
public:
OpenGLPipeline() {
program_ = 0;
// Priority 1 so this gets restored after the shaders.
register_gl_resource_holder(this, "drawcontext_pipeline", 1);
}
~OpenGLPipeline() {
unregister_gl_resource_holder(this);
for (auto &iter : shaders) {
iter->Release();
}
@ -404,15 +383,6 @@ public:
int GetUniformLoc(const char *name);
void GLLost() override {
program_ = 0;
}
void GLRestore() override {
// Shaders will have been restored before the pipeline.
LinkShaders();
}
bool RequiresBuffer() override {
return inputLayout->RequiresBuffer();
}
@ -751,25 +721,11 @@ void OpenGLTexture::AutoGenMipmaps() {
}
}
class OpenGLFramebuffer : public Framebuffer, public GfxResourceHolder {
class OpenGLFramebuffer : public Framebuffer {
public:
OpenGLFramebuffer() {
register_gl_resource_holder(this, "framebuffer", 0);
}
OpenGLFramebuffer() {}
~OpenGLFramebuffer();
void GLLost() override {
handle = 0;
color_texture = 0;
z_stencil_buffer = 0;
z_buffer = 0;
stencil_buffer = 0;
}
void GLRestore() override {
ELOG("Restoring framebuffers not yet implemented");
}
GLuint handle = 0;
GLuint color_texture = 0;
GLuint z_stencil_buffer = 0; // Either this is set, or the two below.
@ -993,14 +949,6 @@ void OpenGLInputLayout::Compile() {
lastBase_ = -1;
}
void OpenGLInputLayout::GLLost() {
id_ = 0;
}
void OpenGLInputLayout::GLRestore() {
Compile();
}
DepthStencilState *OpenGLContext::CreateDepthStencilState(const DepthStencilStateDesc &desc) {
OpenGLDepthStencilState *ds = new OpenGLDepthStencilState();
ds->depthTestEnabled = desc.depthTestEnabled;
@ -1077,7 +1025,7 @@ RasterState *OpenGLContext::CreateRasterState(const RasterStateDesc &desc) {
return rs;
}
class OpenGLBuffer : public Buffer, GfxResourceHolder {
class OpenGLBuffer : public Buffer {
public:
OpenGLBuffer(size_t size, uint32_t flags) {
glGenBuffers(1, &buffer_);
@ -1090,10 +1038,8 @@ public:
totalSize_ = size;
glBindBuffer(target_, buffer_);
glBufferData(target_, size, NULL, usage_);
register_gl_resource_holder(this, "drawcontext_buffer", 0);
}
~OpenGLBuffer() override {
unregister_gl_resource_holder(this);
glDeleteBuffers(1, &buffer_);
}
@ -1102,16 +1048,6 @@ public:
glBindBuffer(target_, buffer_);
}
void GLLost() override {
buffer_ = 0;
}
void GLRestore() override {
ILOG("Recreating vertex buffer after gl_restore");
totalSize_ = 0; // Will cause a new glBufferData call. Should genBuffers again though?
glGenBuffers(1, &buffer_);
}
GLuint buffer_;
GLuint target_;
GLuint usage_;
@ -1847,7 +1783,6 @@ void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBCh
}
OpenGLFramebuffer::~OpenGLFramebuffer() {
unregister_gl_resource_holder(this);
CHECK_GL_ERROR_IF_DEBUG();
if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
if (handle) {

View file

@ -152,22 +152,6 @@ void ScreenManager::sendMessage(const char *msg, const char *value) {
stack_.back().screen->sendMessage(msg, value);
}
void ScreenManager::deviceLost() {
for (size_t i = 0; i < stack_.size(); i++) {
stack_[i].screen->deviceLost();
}
// Dialogs too? Nah, they should only use the standard UI texture anyway.
// TODO: Change this when it becomes necessary.
}
void ScreenManager::deviceRestore() {
for (size_t i = 0; i < stack_.size(); i++) {
stack_[i].screen->deviceRestore();
}
// Dialogs too? Nah, they should only use the standard UI texture anyway.
// TODO: Change this when it becomes necessary.
}
Screen *ScreenManager::topScreen() const {
if (!stack_.empty())
return stack_.back().screen;

View file

@ -52,8 +52,6 @@ public:
virtual void preRender() {}
virtual void render() {}
virtual void postRender() {}
virtual void deviceLost() {}
virtual void deviceRestore() {}
virtual void resized() {}
virtual void dialogFinished(const Screen *dialog, DialogResult result) {}
virtual bool touch(const TouchInput &touch) { return false; }
@ -115,8 +113,6 @@ public:
void render();
void resized();
void deviceLost();
void deviceRestore();
void shutdown();
// Push a dialog box in front. Currently 1-level only.

View file

@ -20,7 +20,6 @@
#include <stdio.h>
#include <SDL.h>
#include <cassert>
#include "gfx/gl_lost_manager.h"
#include "headless/SDLHeadlessHost.h"
@ -114,8 +113,6 @@ bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext *
}
#endif
gl_lost_manager_init();
GraphicsContext *graphicsContext = new GLDummyGraphicsContext();
*ctx = graphicsContext;
gfx_ = graphicsContext;
@ -134,8 +131,6 @@ void SDLHeadlessHost::ShutdownGraphics() {
glContext_ = nullptr;
SDL_DestroyWindow(screen_);
screen_ = nullptr;
gl_lost_manager_shutdown();
}
void SDLHeadlessHost::SwapBuffers() {