mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
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:
commit
3eda310009
27 changed files with 90 additions and 465 deletions
|
@ -868,8 +868,6 @@ add_library(native STATIC
|
||||||
ext/native/gfx/gl_common.h
|
ext/native/gfx/gl_common.h
|
||||||
ext/native/gfx/gl_debug_log.cpp
|
ext/native/gfx/gl_debug_log.cpp
|
||||||
ext/native/gfx/gl_debug_log.h
|
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.cpp
|
||||||
ext/native/gfx/texture_atlas.h
|
ext/native/gfx/texture_atlas.h
|
||||||
ext/native/gfx/d3d9_shader.cpp
|
ext/native/gfx/d3d9_shader.cpp
|
||||||
|
|
|
@ -132,7 +132,6 @@ DrawEngineGLES::DrawEngineGLES() : vai_(256) {
|
||||||
indexGen.Setup(decIndex);
|
indexGen.Setup(decIndex);
|
||||||
|
|
||||||
InitDeviceObjects();
|
InitDeviceObjects();
|
||||||
register_gl_resource_holder(this, "drawengine_gles", 1);
|
|
||||||
|
|
||||||
tessDataTransfer = new TessellationDataTransferGLES(gl_extensions.VersionGEThan(3, 0, 0));
|
tessDataTransfer = new TessellationDataTransferGLES(gl_extensions.VersionGEThan(3, 0, 0));
|
||||||
}
|
}
|
||||||
|
@ -143,8 +142,6 @@ DrawEngineGLES::~DrawEngineGLES() {
|
||||||
FreeMemoryPages(decIndex, DECODED_INDEX_BUFFER_SIZE);
|
FreeMemoryPages(decIndex, DECODED_INDEX_BUFFER_SIZE);
|
||||||
FreeMemoryPages(splineBuffer, SPLINE_BUFFER_SIZE);
|
FreeMemoryPages(splineBuffer, SPLINE_BUFFER_SIZE);
|
||||||
|
|
||||||
unregister_gl_resource_holder(this);
|
|
||||||
|
|
||||||
delete tessDataTransfer;
|
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 {
|
struct GlTypeInfo {
|
||||||
u16 type;
|
u16 type;
|
||||||
u8 count;
|
u8 count;
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
#include "GPU/Common/GPUStateUtils.h"
|
#include "GPU/Common/GPUStateUtils.h"
|
||||||
#include "GPU/GLES/FragmentShaderGeneratorGLES.h"
|
#include "GPU/GLES/FragmentShaderGeneratorGLES.h"
|
||||||
#include "gfx/gl_common.h"
|
#include "gfx/gl_common.h"
|
||||||
#include "gfx/gl_lost_manager.h"
|
|
||||||
|
|
||||||
class LinkedShader;
|
class LinkedShader;
|
||||||
class ShaderManagerGLES;
|
class ShaderManagerGLES;
|
||||||
|
@ -100,7 +99,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handles transform, lighting and drawing.
|
// Handles transform, lighting and drawing.
|
||||||
class DrawEngineGLES : public DrawEngineCommon, public GfxResourceHolder {
|
class DrawEngineGLES : public DrawEngineCommon {
|
||||||
public:
|
public:
|
||||||
DrawEngineGLES();
|
DrawEngineGLES();
|
||||||
virtual ~DrawEngineGLES();
|
virtual ~DrawEngineGLES();
|
||||||
|
@ -122,8 +121,6 @@ public:
|
||||||
void RestoreVAO();
|
void RestoreVAO();
|
||||||
void InitDeviceObjects();
|
void InitDeviceObjects();
|
||||||
void DestroyDeviceObjects();
|
void DestroyDeviceObjects();
|
||||||
void GLLost() override;
|
|
||||||
void GLRestore() override;
|
|
||||||
|
|
||||||
void ClearTrackedVertexArrays() override;
|
void ClearTrackedVertexArrays() override;
|
||||||
void DecimateTrackedVertexArrays();
|
void DecimateTrackedVertexArrays();
|
||||||
|
|
|
@ -75,6 +75,8 @@ static const char basic_vs[] =
|
||||||
" gl_Position = a_position;\n"
|
" gl_Position = a_position;\n"
|
||||||
"}\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 ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format);
|
||||||
|
|
||||||
void FramebufferManagerGLES::DisableState() {
|
void FramebufferManagerGLES::DisableState() {
|
||||||
|
@ -189,25 +191,11 @@ void FramebufferManagerGLES::BindPostShader(const PostShaderUniforms &uniforms)
|
||||||
glUniform1f(videoLoc_, uniforms.video);
|
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) :
|
FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) :
|
||||||
FramebufferManagerCommon(draw),
|
FramebufferManagerCommon(draw),
|
||||||
drawPixelsTex_(0),
|
drawPixelsTex_(0),
|
||||||
drawPixelsTexFormat_(GE_FORMAT_INVALID),
|
drawPixelsTexFormat_(GE_FORMAT_INVALID),
|
||||||
convBuf_(nullptr),
|
convBuf_(nullptr),
|
||||||
draw2dprogram_(nullptr),
|
|
||||||
postShaderProgram_(nullptr),
|
|
||||||
stencilUploadProgram_(nullptr),
|
|
||||||
videoLoc_(-1),
|
videoLoc_(-1),
|
||||||
timeLoc_(-1),
|
timeLoc_(-1),
|
||||||
pixelDeltaLoc_(-1),
|
pixelDeltaLoc_(-1),
|
||||||
|
@ -219,6 +207,7 @@ FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) :
|
||||||
{
|
{
|
||||||
needBackBufferYSwap_ = true;
|
needBackBufferYSwap_ = true;
|
||||||
needGLESRebinds_ = true;
|
needGLESRebinds_ = true;
|
||||||
|
CreateDeviceObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManagerGLES::Init() {
|
void FramebufferManagerGLES::Init() {
|
||||||
|
@ -243,19 +232,38 @@ void FramebufferManagerGLES::SetDrawEngine(DrawEngineGLES *td) {
|
||||||
drawEngine_ = td;
|
drawEngine_ = td;
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferManagerGLES::~FramebufferManagerGLES() {
|
void FramebufferManagerGLES::CreateDeviceObjects() {
|
||||||
if (drawPixelsTex_)
|
CompileDraw2DProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferManagerGLES::DestroyDeviceObjects() {
|
||||||
|
if (draw2dprogram_) {
|
||||||
|
glsl_destroy(draw2dprogram_);
|
||||||
|
draw2dprogram_ = nullptr;
|
||||||
|
}
|
||||||
|
if (postShaderProgram_) {
|
||||||
|
glsl_destroy(postShaderProgram_);
|
||||||
|
postShaderProgram_ = nullptr;
|
||||||
|
}
|
||||||
|
if (drawPixelsTex_) {
|
||||||
glDeleteTextures(1, &drawPixelsTex_);
|
glDeleteTextures(1, &drawPixelsTex_);
|
||||||
DestroyDraw2DProgram();
|
drawPixelsTex_ = 0;
|
||||||
|
}
|
||||||
if (stencilUploadProgram_) {
|
if (stencilUploadProgram_) {
|
||||||
glsl_destroy(stencilUploadProgram_);
|
glsl_destroy(stencilUploadProgram_);
|
||||||
|
stencilUploadProgram_ = nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto it = tempFBOs_.begin(), end = tempFBOs_.end(); it != end; ++it) {
|
FramebufferManagerGLES::~FramebufferManagerGLES() {
|
||||||
it->second.fbo->Release();
|
DestroyDeviceObjects();
|
||||||
|
|
||||||
|
if (pixelBufObj_) {
|
||||||
|
for (int i = 0; i < MAX_PBO; i++) {
|
||||||
|
glDeleteBuffers(1, &pixelBufObj_[i].handle);
|
||||||
|
}
|
||||||
|
delete[] pixelBufObj_;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] pixelBufObj_;
|
|
||||||
delete [] convBuf_;
|
delete [] convBuf_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,7 +769,6 @@ void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u
|
||||||
|
|
||||||
void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) {
|
void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) {
|
||||||
CHECK_GL_ERROR_IF_DEBUG();
|
CHECK_GL_ERROR_IF_DEBUG();
|
||||||
const int MAX_PBO = 2;
|
|
||||||
GLubyte *packed = 0;
|
GLubyte *packed = 0;
|
||||||
bool unbind = false;
|
bool unbind = false;
|
||||||
const u8 nextPBO = (currentPBO_ + 1) % MAX_PBO;
|
const u8 nextPBO = (currentPBO_ + 1) % MAX_PBO;
|
||||||
|
@ -1005,7 +1012,12 @@ void FramebufferManagerGLES::EndFrame() {
|
||||||
|
|
||||||
void FramebufferManagerGLES::DeviceLost() {
|
void FramebufferManagerGLES::DeviceLost() {
|
||||||
DestroyAllFBOs();
|
DestroyAllFBOs();
|
||||||
DestroyDraw2DProgram();
|
DestroyDeviceObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferManagerGLES::DeviceRestore(Draw::DrawContext *draw) {
|
||||||
|
draw_ = draw;
|
||||||
|
CreateDeviceObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManagerGLES::DestroyAllFBOs() {
|
void FramebufferManagerGLES::DestroyAllFBOs() {
|
||||||
|
@ -1046,8 +1058,6 @@ void FramebufferManagerGLES::Resized() {
|
||||||
DestroyAllFBOs();
|
DestroyAllFBOs();
|
||||||
}
|
}
|
||||||
|
|
||||||
DestroyDraw2DProgram();
|
|
||||||
|
|
||||||
#ifndef USING_GLES2
|
#ifndef USING_GLES2
|
||||||
if (g_Config.iInternalResolution == 0) {
|
if (g_Config.iInternalResolution == 0) {
|
||||||
glLineWidth(std::max(1, (int)(renderWidth_ / 480)));
|
glLineWidth(std::max(1, (int)(renderWidth_ / 480)));
|
||||||
|
@ -1057,10 +1067,6 @@ void FramebufferManagerGLES::Resized() {
|
||||||
glPointSize((float)g_Config.iInternalResolution);
|
glPointSize((float)g_Config.iInternalResolution);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!draw2dprogram_) {
|
|
||||||
CompileDraw2DProgram();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
||||||
|
@ -1069,4 +1075,4 @@ bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
||||||
buffer.Allocate(w, h, GPU_DBG_FORMAT_888_RGB, true);
|
buffer.Allocate(w, h, GPU_DBG_FORMAT_888_RGB, true);
|
||||||
draw_->CopyFramebufferToMemorySync(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8_UNORM, buffer.GetData(), w);
|
draw_->CopyFramebufferToMemorySync(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8_UNORM, buffer.GetData(), w);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
|
@ -83,6 +83,8 @@ public:
|
||||||
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
||||||
virtual void RebindFramebuffer() override;
|
virtual void RebindFramebuffer() override;
|
||||||
|
|
||||||
|
void DeviceRestore(Draw::DrawContext *draw);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetViewport2D(int x, int y, int w, int h) override;
|
void SetViewport2D(int x, int y, int w, int h) override;
|
||||||
void DisableState() override;
|
void DisableState() override;
|
||||||
|
@ -94,6 +96,9 @@ protected:
|
||||||
void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
|
void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void CreateDeviceObjects();
|
||||||
|
void DestroyDeviceObjects();
|
||||||
|
|
||||||
void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) override;
|
void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) override;
|
||||||
void Bind2DShader() override;
|
void Bind2DShader() override;
|
||||||
void BindPostShader(const PostShaderUniforms &uniforms) override;
|
void BindPostShader(const PostShaderUniforms &uniforms) override;
|
||||||
|
@ -113,10 +118,9 @@ private:
|
||||||
|
|
||||||
u8 *convBuf_;
|
u8 *convBuf_;
|
||||||
u32 convBufSize_;
|
u32 convBufSize_;
|
||||||
GLSLProgram *draw2dprogram_;
|
GLSLProgram *draw2dprogram_ = nullptr;
|
||||||
GLSLProgram *plainColorProgram_;
|
GLSLProgram *postShaderProgram_ = nullptr;
|
||||||
GLSLProgram *postShaderProgram_;
|
GLSLProgram *stencilUploadProgram_ = nullptr;
|
||||||
GLSLProgram *stencilUploadProgram_;
|
|
||||||
int plainColorLoc_;
|
int plainColorLoc_;
|
||||||
int videoLoc_;
|
int videoLoc_;
|
||||||
int timeLoc_;
|
int timeLoc_;
|
||||||
|
|
|
@ -385,23 +385,24 @@ void GPU_GLES::BuildReportingInfo() {
|
||||||
|
|
||||||
void GPU_GLES::DeviceLost() {
|
void GPU_GLES::DeviceLost() {
|
||||||
ILOG("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);
|
shaderManagerGL_->ClearCache(false);
|
||||||
textureCacheGL_->Clear(false);
|
textureCacheGL_->Clear(false);
|
||||||
fragmentTestCache_.Clear(false);
|
fragmentTestCache_.Clear(false);
|
||||||
depalShaderCache_.Clear();
|
depalShaderCache_.Clear();
|
||||||
|
drawEngine_.ClearTrackedVertexArrays();
|
||||||
framebufferManagerGL_->DeviceLost();
|
framebufferManagerGL_->DeviceLost();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_GLES::DeviceRestore() {
|
void GPU_GLES::DeviceRestore() {
|
||||||
|
draw_ = (Draw::DrawContext *)PSP_CoreParameter().graphicsContext->GetDrawContext();
|
||||||
ILOG("GPU_GLES: DeviceRestore");
|
ILOG("GPU_GLES: DeviceRestore");
|
||||||
|
|
||||||
UpdateCmdInfo();
|
UpdateCmdInfo();
|
||||||
UpdateVsyncInterval(true);
|
UpdateVsyncInterval(true);
|
||||||
|
|
||||||
|
textureCacheGL_->DeviceRestore(draw_);
|
||||||
|
framebufferManagerGL_->DeviceRestore(draw_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_GLES::Reinitialize() {
|
void GPU_GLES::Reinitialize() {
|
||||||
|
|
|
@ -917,6 +917,11 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, w, h, components2, dstFmt, pixelData);
|
glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, w, h, components2, dstFmt, pixelData);
|
||||||
} else {
|
} else {
|
||||||
PROFILE_THIS_SCOPE("loadtex");
|
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())
|
if (IsFakeMipmapChange())
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, components, w, h, 0, components2, dstFmt, pixelData);
|
glTexImage2D(GL_TEXTURE_2D, 0, components, w, h, 0, components2, dstFmt, pixelData);
|
||||||
else
|
else
|
||||||
|
@ -925,7 +930,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
|
||||||
// TODO: We really, really should avoid calling glGetError.
|
// TODO: We really, really should avoid calling glGetError.
|
||||||
GLenum err = glGetError();
|
GLenum err = glGetError();
|
||||||
if (err == GL_OUT_OF_MEMORY) {
|
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;
|
lowMemoryMode_ = true;
|
||||||
decimationCounter_ = 0;
|
decimationCounter_ = 0;
|
||||||
Decimate();
|
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);
|
host->NotifyUserMessage(err->T("Warning: Video memory FULL, switching to slow caching mode"), 2.0f);
|
||||||
}
|
}
|
||||||
} else if (err != GL_NO_ERROR) {
|
} 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.
|
// 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)",
|
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);
|
w, h, level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1066,3 +1065,7 @@ bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level)
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureCacheGLES::DeviceRestore(Draw::DrawContext *draw) {
|
||||||
|
draw_ = draw;
|
||||||
|
}
|
||||||
|
|
|
@ -69,6 +69,8 @@ public:
|
||||||
void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight);
|
void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight);
|
||||||
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
|
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
|
||||||
|
|
||||||
|
void DeviceRestore(Draw::DrawContext *draw);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void BindTexture(TexCacheEntry *entry) override;
|
void BindTexture(TexCacheEntry *entry) override;
|
||||||
void Unbind() override;
|
void Unbind() override;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "debugger_memorytex.h"
|
#include "debugger_memorytex.h"
|
||||||
#include "gfx/GLStateCache.h"
|
#include "gfx/GLStateCache.h"
|
||||||
#include "gfx/gl_common.h"
|
#include "gfx/gl_common.h"
|
||||||
#include "gfx/gl_lost_manager.h"
|
|
||||||
#include "ui_debugger_memorytex.h"
|
#include "ui_debugger_memorytex.h"
|
||||||
#include "Core/MemMap.h"
|
#include "Core/MemMap.h"
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
|
|
|
@ -1163,24 +1163,6 @@ void EmuScreen::renderUI() {
|
||||||
screenManager()->getUIContext()->End();
|
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() {
|
void EmuScreen::autoLoad() {
|
||||||
//check if save state has save, if so, load
|
//check if save state has save, if so, load
|
||||||
int lastSlot = SaveState::GetNewestSlot(gamePath_);
|
int lastSlot = SaveState::GetNewestSlot(gamePath_);
|
||||||
|
|
|
@ -40,8 +40,6 @@ public:
|
||||||
void render() override;
|
void render() override;
|
||||||
void preRender() override;
|
void preRender() override;
|
||||||
void postRender() override;
|
void postRender() override;
|
||||||
void deviceLost() override;
|
|
||||||
void deviceRestore() override;
|
|
||||||
void dialogFinished(const Screen *dialog, DialogResult result) override;
|
void dialogFinished(const Screen *dialog, DialogResult result) override;
|
||||||
void sendMessage(const char *msg, const char *value) override;
|
void sendMessage(const char *msg, const char *value) override;
|
||||||
void resized() override;
|
void resized() override;
|
||||||
|
|
|
@ -52,7 +52,6 @@
|
||||||
#include "net/resolve.h"
|
#include "net/resolve.h"
|
||||||
#include "gfx_es2/draw_text.h"
|
#include "gfx_es2/draw_text.h"
|
||||||
#include "gfx_es2/gpu_features.h"
|
#include "gfx_es2/gpu_features.h"
|
||||||
#include "gfx/gl_lost_manager.h"
|
|
||||||
#include "i18n/i18n.h"
|
#include "i18n/i18n.h"
|
||||||
#include "input/input_state.h"
|
#include "input/input_state.h"
|
||||||
#include "math/fast/fast_math.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.
|
// 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.
|
// When it's reset we don't want to forget all our managed things.
|
||||||
SetGPUBackend((GPUBackend) g_Config.iGPUBackend);
|
SetGPUBackend((GPUBackend) g_Config.iGPUBackend);
|
||||||
if (GetGPUBackend() == GPUBackend::OPENGL) {
|
|
||||||
gl_lost_manager_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must be done restarting by now.
|
// Must be done restarting by now.
|
||||||
restarting = false;
|
restarting = false;
|
||||||
|
@ -694,12 +690,18 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) {
|
||||||
|
|
||||||
g_gameInfoCache = new GameInfoCache();
|
g_gameInfoCache = new GameInfoCache();
|
||||||
|
|
||||||
|
if (gpu)
|
||||||
|
gpu->DeviceRestore();
|
||||||
|
|
||||||
g_graphicsInited = true;
|
g_graphicsInited = true;
|
||||||
ILOG("NativeInitGraphics completed");
|
ILOG("NativeInitGraphics completed");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeShutdownGraphics() {
|
void NativeShutdownGraphics() {
|
||||||
|
if (gpu)
|
||||||
|
gpu->DeviceLost();
|
||||||
|
|
||||||
g_graphicsInited = false;
|
g_graphicsInited = false;
|
||||||
ILOG("NativeShutdownGraphics");
|
ILOG("NativeShutdownGraphics");
|
||||||
|
|
||||||
|
@ -860,15 +862,17 @@ void NativeRender(GraphicsContext *graphicsContext) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test lost/restore on PC
|
||||||
|
#if 0
|
||||||
|
if (gpu) {
|
||||||
|
gpu->DeviceLost();
|
||||||
|
gpu->DeviceRestore();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
graphicsContext->Resize();
|
graphicsContext->Resize();
|
||||||
screenManager->resized();
|
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.
|
// TODO: Move this to new GraphicsContext objects for each backend.
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
if (GetGPUBackend() == GPUBackend::OPENGL) {
|
if (GetGPUBackend() == GPUBackend::OPENGL) {
|
||||||
|
@ -951,26 +955,6 @@ void NativeUpdate() {
|
||||||
screenManager->update();
|
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() {
|
bool NativeIsAtTopLevel() {
|
||||||
Screen *currentScreen = screenManager->topScreen();
|
Screen *currentScreen = screenManager->topScreen();
|
||||||
if (currentScreen) {
|
if (currentScreen) {
|
||||||
|
@ -1127,9 +1111,6 @@ void NativeShutdown() {
|
||||||
screenManager = nullptr;
|
screenManager = nullptr;
|
||||||
|
|
||||||
host->ShutdownGraphics();
|
host->ShutdownGraphics();
|
||||||
if (GetGPUBackend() == GPUBackend::OPENGL) {
|
|
||||||
gl_lost_manager_shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !PPSSPP_PLATFORM(UWP)
|
#if !PPSSPP_PLATFORM(UWP)
|
||||||
delete host;
|
delete host;
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#include "thin3d/thin3d.h"
|
#include "thin3d/thin3d.h"
|
||||||
#include "Core/Config.h"
|
#include "Core/Config.h"
|
||||||
#include "gfx/gl_lost_manager.h"
|
|
||||||
|
|
||||||
enum ImageFileType {
|
enum ImageFileType {
|
||||||
PNG,
|
PNG,
|
||||||
|
@ -14,36 +13,14 @@ enum ImageFileType {
|
||||||
TYPE_UNKNOWN,
|
TYPE_UNKNOWN,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ManagedTexture : public GfxResourceHolder {
|
class ManagedTexture {
|
||||||
public:
|
public:
|
||||||
ManagedTexture(Draw::DrawContext *draw) : draw_(draw) {
|
ManagedTexture(Draw::DrawContext *draw) : draw_(draw) {
|
||||||
if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL)
|
|
||||||
register_gl_resource_holder(this, "managed_texture", 0);
|
|
||||||
}
|
}
|
||||||
~ManagedTexture() {
|
~ManagedTexture() {
|
||||||
if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL)
|
|
||||||
unregister_gl_resource_holder(this);
|
|
||||||
if (texture_)
|
if (texture_)
|
||||||
texture_->Release();
|
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 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);
|
bool LoadFromFileData(const uint8_t *data, size_t dataSize, ImageFileType type = ImageFileType::DETECT, bool generateMips = false);
|
||||||
|
|
|
@ -437,7 +437,6 @@ static float dp_xscale = 1.0f;
|
||||||
static float dp_yscale = 1.0f;
|
static float dp_yscale = 1.0f;
|
||||||
|
|
||||||
static bool renderer_inited = false;
|
static bool renderer_inited = false;
|
||||||
static bool renderer_ever_inited = false;
|
|
||||||
static bool sustainedPerfSupported = false;
|
static bool sustainedPerfSupported = false;
|
||||||
|
|
||||||
// See NativeQueryConfig("androidJavaGL") to change this value.
|
// See NativeQueryConfig("androidJavaGL") to change this value.
|
||||||
|
@ -609,7 +608,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init
|
||||||
PROFILE_INIT();
|
PROFILE_INIT();
|
||||||
|
|
||||||
renderer_inited = false;
|
renderer_inited = false;
|
||||||
renderer_ever_inited = false;
|
|
||||||
androidVersion = jAndroidVersion;
|
androidVersion = jAndroidVersion;
|
||||||
deviceType = jdeviceType;
|
deviceType = jdeviceType;
|
||||||
|
|
||||||
|
@ -748,16 +746,16 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env,
|
||||||
|
|
||||||
if (renderer_inited) {
|
if (renderer_inited) {
|
||||||
ILOG("NativeApp.displayInit() restoring");
|
ILOG("NativeApp.displayInit() restoring");
|
||||||
NativeDeviceLost();
|
|
||||||
NativeShutdownGraphics();
|
NativeShutdownGraphics();
|
||||||
NativeDeviceRestore();
|
delete graphicsContext;
|
||||||
|
|
||||||
|
graphicsContext = new AndroidJavaEGLGraphicsContext();
|
||||||
NativeInitGraphics(graphicsContext);
|
NativeInitGraphics(graphicsContext);
|
||||||
ILOG("Restored.");
|
ILOG("Restored.");
|
||||||
} else {
|
} else {
|
||||||
ILOG("NativeApp.displayInit() first time");
|
ILOG("NativeApp.displayInit() first time");
|
||||||
NativeInitGraphics(graphicsContext);
|
NativeInitGraphics(graphicsContext);
|
||||||
renderer_inited = true;
|
renderer_inited = true;
|
||||||
renderer_ever_inited = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeMessageReceived("recreateviews", "");
|
NativeMessageReceived("recreateviews", "");
|
||||||
|
@ -1150,13 +1148,9 @@ retry:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!exitRenderLoop && !renderer_inited) {
|
if (!exitRenderLoop) {
|
||||||
NativeInitGraphics(graphicsContext);
|
NativeInitGraphics(graphicsContext);
|
||||||
if (renderer_ever_inited) {
|
|
||||||
NativeDeviceRestore();
|
|
||||||
}
|
|
||||||
renderer_inited = true;
|
renderer_inited = true;
|
||||||
renderer_ever_inited = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!exitRenderLoop) {
|
while (!exitRenderLoop) {
|
||||||
|
@ -1180,8 +1174,7 @@ retry:
|
||||||
if (g_gameInfoCache)
|
if (g_gameInfoCache)
|
||||||
g_gameInfoCache->WorkQueue()->Flush();
|
g_gameInfoCache->WorkQueue()->Flush();
|
||||||
|
|
||||||
if (renderer_inited)
|
NativeShutdownGraphics();
|
||||||
NativeDeviceLost();
|
|
||||||
renderer_inited = false;
|
renderer_inited = false;
|
||||||
|
|
||||||
ILOG("Shutting down graphics context.");
|
ILOG("Shutting down graphics context.");
|
||||||
|
|
|
@ -77,7 +77,6 @@ LOCAL_SRC_FILES :=\
|
||||||
gfx_es2/draw_text_android.cpp.arm \
|
gfx_es2/draw_text_android.cpp.arm \
|
||||||
gfx/GLStateCache.cpp.arm \
|
gfx/GLStateCache.cpp.arm \
|
||||||
gfx/gl_debug_log.cpp \
|
gfx/gl_debug_log.cpp \
|
||||||
gfx/gl_lost_manager.cpp \
|
|
||||||
gfx/texture_atlas.cpp \
|
gfx/texture_atlas.cpp \
|
||||||
image/zim_load.cpp \
|
image/zim_load.cpp \
|
||||||
image/zim_save.cpp \
|
image/zim_save.cpp \
|
||||||
|
|
|
@ -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.
|
// Should not initialize anything screen-size-dependent - do that in NativeResized.
|
||||||
bool NativeInitGraphics(GraphicsContext *graphicsContext);
|
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
|
// 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,
|
// 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.
|
// and only write dp_xres and dp_yres.
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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();
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
#include "base/colorutil.h"
|
#include "base/colorutil.h"
|
||||||
#include "gfx/gl_lost_manager.h"
|
|
||||||
#include "gfx/texture_atlas.h"
|
#include "gfx/texture_atlas.h"
|
||||||
#include "math/geom2d.h"
|
#include "math/geom2d.h"
|
||||||
#include "math/lin/matrix4x4.h"
|
#include "math/lin/matrix4x4.h"
|
||||||
|
|
|
@ -49,7 +49,6 @@ GLSLProgram *glsl_create(const char *vshader, const char *fshader, std::string *
|
||||||
delete program;
|
delete program;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
register_gl_resource_holder(program, "glsl_program", 0);
|
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +69,6 @@ GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src
|
||||||
delete program;
|
delete program;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
register_gl_resource_holder(program, "glsl_program_src", 0);
|
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,23 +218,6 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) {
|
||||||
return true;
|
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) {
|
int glsl_attrib_loc(const GLSLProgram *program, const char *name) {
|
||||||
return glGetAttribLocation(program->program_, 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) {
|
void glsl_destroy(GLSLProgram *program) {
|
||||||
if (program) {
|
if (program) {
|
||||||
unregister_gl_resource_holder(program);
|
|
||||||
glDeleteShader(program->vsh_);
|
glDeleteShader(program->vsh_);
|
||||||
glDeleteShader(program->fsh_);
|
glDeleteShader(program->fsh_);
|
||||||
glDeleteProgram(program->program_);
|
glDeleteProgram(program->program_);
|
||||||
|
|
|
@ -7,13 +7,12 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "gfx/gl_lost_manager.h"
|
|
||||||
#include "gfx/gl_common.h"
|
#include "gfx/gl_common.h"
|
||||||
|
|
||||||
// Represent a compiled and linked vshader/fshader pair.
|
// Represent a compiled and linked vshader/fshader pair.
|
||||||
// A just-constructed object is valid but cannot be used as a shader program, meaning that
|
// 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.
|
// yes, you can declare these as globals if you like.
|
||||||
struct GLSLProgram : public GfxResourceHolder {
|
struct GLSLProgram {
|
||||||
char name[16];
|
char name[16];
|
||||||
char vshader_filename[256];
|
char vshader_filename[256];
|
||||||
char fshader_filename[256];
|
char fshader_filename[256];
|
||||||
|
@ -42,9 +41,6 @@ struct GLSLProgram : public GfxResourceHolder {
|
||||||
GLuint vsh_;
|
GLuint vsh_;
|
||||||
GLuint fsh_;
|
GLuint fsh_;
|
||||||
GLuint program_;
|
GLuint program_;
|
||||||
|
|
||||||
void GLLost() override;
|
|
||||||
void GLRestore() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// C API, old skool. Not much point either...
|
// C API, old skool. Not much point either...
|
||||||
|
|
|
@ -234,7 +234,6 @@
|
||||||
<ClInclude Include="gfx\GLStateCache.h" />
|
<ClInclude Include="gfx\GLStateCache.h" />
|
||||||
<ClInclude Include="gfx\gl_common.h" />
|
<ClInclude Include="gfx\gl_common.h" />
|
||||||
<ClInclude Include="gfx\gl_debug_log.h" />
|
<ClInclude Include="gfx\gl_debug_log.h" />
|
||||||
<ClInclude Include="gfx\gl_lost_manager.h" />
|
|
||||||
<ClInclude Include="gfx\texture_atlas.h" />
|
<ClInclude Include="gfx\texture_atlas.h" />
|
||||||
<ClInclude Include="gfx_es2\draw_text_android.h" />
|
<ClInclude Include="gfx_es2\draw_text_android.h" />
|
||||||
<ClInclude Include="gfx_es2\draw_text_qt.h" />
|
<ClInclude Include="gfx_es2\draw_text_qt.h" />
|
||||||
|
@ -693,7 +692,6 @@
|
||||||
<ClCompile Include="gfx\d3d9_state.cpp" />
|
<ClCompile Include="gfx\d3d9_state.cpp" />
|
||||||
<ClCompile Include="gfx\GLStateCache.cpp" />
|
<ClCompile Include="gfx\GLStateCache.cpp" />
|
||||||
<ClCompile Include="gfx\gl_debug_log.cpp" />
|
<ClCompile Include="gfx\gl_debug_log.cpp" />
|
||||||
<ClCompile Include="gfx\gl_lost_manager.cpp" />
|
|
||||||
<ClCompile Include="gfx\texture_atlas.cpp" />
|
<ClCompile Include="gfx\texture_atlas.cpp" />
|
||||||
<ClCompile Include="gfx_es2\draw_text_android.cpp" />
|
<ClCompile Include="gfx_es2\draw_text_android.cpp" />
|
||||||
<ClCompile Include="gfx_es2\draw_text_qt.cpp" />
|
<ClCompile Include="gfx_es2\draw_text_qt.cpp" />
|
||||||
|
|
|
@ -74,9 +74,6 @@
|
||||||
<ClInclude Include="base\basictypes.h">
|
<ClInclude Include="base\basictypes.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="gfx\gl_lost_manager.h">
|
|
||||||
<Filter>gfx</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="gfx\texture_atlas.h">
|
<ClInclude Include="gfx\texture_atlas.h">
|
||||||
<Filter>gfx</Filter>
|
<Filter>gfx</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -370,9 +367,6 @@
|
||||||
<ClCompile Include="file\zip_read.cpp">
|
<ClCompile Include="file\zip_read.cpp">
|
||||||
<Filter>file</Filter>
|
<Filter>file</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="gfx\gl_lost_manager.cpp">
|
|
||||||
<Filter>gfx</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="gfx\texture_atlas.cpp">
|
<ClCompile Include="gfx\texture_atlas.cpp">
|
||||||
<Filter>gfx</Filter>
|
<Filter>gfx</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include "gfx/gl_debug_log.h"
|
#include "gfx/gl_debug_log.h"
|
||||||
#include "gfx/GLStateCache.h"
|
#include "gfx/GLStateCache.h"
|
||||||
#include "gfx_es2/gpu_features.h"
|
#include "gfx_es2/gpu_features.h"
|
||||||
#include "gfx/gl_lost_manager.h"
|
|
||||||
|
|
||||||
#ifdef IOS
|
#ifdef IOS
|
||||||
extern void bindDefaultFBO();
|
extern void bindDefaultFBO();
|
||||||
|
@ -274,11 +273,10 @@ GLuint ShaderStageToOpenGL(ShaderStage stage) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenGLShaderModule : public ShaderModule, public GfxResourceHolder {
|
class OpenGLShaderModule : public ShaderModule {
|
||||||
public:
|
public:
|
||||||
OpenGLShaderModule(ShaderStage stage) : stage_(stage) {
|
OpenGLShaderModule(ShaderStage stage) : stage_(stage) {
|
||||||
ILOG("Shader module created (%p)", this);
|
ILOG("Shader module created (%p)", this);
|
||||||
register_gl_resource_holder(this, "drawcontext_shader_module", 0);
|
|
||||||
glstage_ = ShaderStageToOpenGL(stage);
|
glstage_ = ShaderStageToOpenGL(stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +284,6 @@ public:
|
||||||
ILOG("Shader module destroyed (%p)", this);
|
ILOG("Shader module destroyed (%p)", this);
|
||||||
if (shader_)
|
if (shader_)
|
||||||
glDeleteShader(shader_);
|
glDeleteShader(shader_);
|
||||||
unregister_gl_resource_holder(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compile(ShaderLanguage language, const uint8_t *data, size_t dataSize);
|
bool Compile(ShaderLanguage language, const uint8_t *data, size_t dataSize);
|
||||||
|
@ -302,19 +299,6 @@ public:
|
||||||
return stage_;
|
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:
|
private:
|
||||||
ShaderStage stage_;
|
ShaderStage stage_;
|
||||||
ShaderLanguage language_;
|
ShaderLanguage language_;
|
||||||
|
@ -355,15 +339,13 @@ bool OpenGLShaderModule::Compile(ShaderLanguage language, const uint8_t *data, s
|
||||||
return ok_;
|
return ok_;
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenGLInputLayout : public InputLayout, GfxResourceHolder {
|
class OpenGLInputLayout : public InputLayout {
|
||||||
public:
|
public:
|
||||||
~OpenGLInputLayout();
|
~OpenGLInputLayout();
|
||||||
|
|
||||||
void Apply(const void *base = nullptr);
|
void Apply(const void *base = nullptr);
|
||||||
void Unapply();
|
void Unapply();
|
||||||
void Compile();
|
void Compile();
|
||||||
void GLRestore() override;
|
|
||||||
void GLLost() override;
|
|
||||||
bool RequiresBuffer() {
|
bool RequiresBuffer() {
|
||||||
return id_ != 0;
|
return id_ != 0;
|
||||||
}
|
}
|
||||||
|
@ -381,15 +363,12 @@ struct UniformInfo {
|
||||||
int loc_;
|
int loc_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class OpenGLPipeline : public Pipeline, GfxResourceHolder {
|
class OpenGLPipeline : public Pipeline {
|
||||||
public:
|
public:
|
||||||
OpenGLPipeline() {
|
OpenGLPipeline() {
|
||||||
program_ = 0;
|
program_ = 0;
|
||||||
// Priority 1 so this gets restored after the shaders.
|
|
||||||
register_gl_resource_holder(this, "drawcontext_pipeline", 1);
|
|
||||||
}
|
}
|
||||||
~OpenGLPipeline() {
|
~OpenGLPipeline() {
|
||||||
unregister_gl_resource_holder(this);
|
|
||||||
for (auto &iter : shaders) {
|
for (auto &iter : shaders) {
|
||||||
iter->Release();
|
iter->Release();
|
||||||
}
|
}
|
||||||
|
@ -404,15 +383,6 @@ public:
|
||||||
|
|
||||||
int GetUniformLoc(const char *name);
|
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 {
|
bool RequiresBuffer() override {
|
||||||
return inputLayout->RequiresBuffer();
|
return inputLayout->RequiresBuffer();
|
||||||
}
|
}
|
||||||
|
@ -751,25 +721,11 @@ void OpenGLTexture::AutoGenMipmaps() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenGLFramebuffer : public Framebuffer, public GfxResourceHolder {
|
class OpenGLFramebuffer : public Framebuffer {
|
||||||
public:
|
public:
|
||||||
OpenGLFramebuffer() {
|
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 handle = 0;
|
||||||
GLuint color_texture = 0;
|
GLuint color_texture = 0;
|
||||||
GLuint z_stencil_buffer = 0; // Either this is set, or the two below.
|
GLuint z_stencil_buffer = 0; // Either this is set, or the two below.
|
||||||
|
@ -993,14 +949,6 @@ void OpenGLInputLayout::Compile() {
|
||||||
lastBase_ = -1;
|
lastBase_ = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLInputLayout::GLLost() {
|
|
||||||
id_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLInputLayout::GLRestore() {
|
|
||||||
Compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
DepthStencilState *OpenGLContext::CreateDepthStencilState(const DepthStencilStateDesc &desc) {
|
DepthStencilState *OpenGLContext::CreateDepthStencilState(const DepthStencilStateDesc &desc) {
|
||||||
OpenGLDepthStencilState *ds = new OpenGLDepthStencilState();
|
OpenGLDepthStencilState *ds = new OpenGLDepthStencilState();
|
||||||
ds->depthTestEnabled = desc.depthTestEnabled;
|
ds->depthTestEnabled = desc.depthTestEnabled;
|
||||||
|
@ -1077,7 +1025,7 @@ RasterState *OpenGLContext::CreateRasterState(const RasterStateDesc &desc) {
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenGLBuffer : public Buffer, GfxResourceHolder {
|
class OpenGLBuffer : public Buffer {
|
||||||
public:
|
public:
|
||||||
OpenGLBuffer(size_t size, uint32_t flags) {
|
OpenGLBuffer(size_t size, uint32_t flags) {
|
||||||
glGenBuffers(1, &buffer_);
|
glGenBuffers(1, &buffer_);
|
||||||
|
@ -1090,10 +1038,8 @@ public:
|
||||||
totalSize_ = size;
|
totalSize_ = size;
|
||||||
glBindBuffer(target_, buffer_);
|
glBindBuffer(target_, buffer_);
|
||||||
glBufferData(target_, size, NULL, usage_);
|
glBufferData(target_, size, NULL, usage_);
|
||||||
register_gl_resource_holder(this, "drawcontext_buffer", 0);
|
|
||||||
}
|
}
|
||||||
~OpenGLBuffer() override {
|
~OpenGLBuffer() override {
|
||||||
unregister_gl_resource_holder(this);
|
|
||||||
glDeleteBuffers(1, &buffer_);
|
glDeleteBuffers(1, &buffer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1102,16 +1048,6 @@ public:
|
||||||
glBindBuffer(target_, buffer_);
|
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 buffer_;
|
||||||
GLuint target_;
|
GLuint target_;
|
||||||
GLuint usage_;
|
GLuint usage_;
|
||||||
|
@ -1847,7 +1783,6 @@ void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBCh
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLFramebuffer::~OpenGLFramebuffer() {
|
OpenGLFramebuffer::~OpenGLFramebuffer() {
|
||||||
unregister_gl_resource_holder(this);
|
|
||||||
CHECK_GL_ERROR_IF_DEBUG();
|
CHECK_GL_ERROR_IF_DEBUG();
|
||||||
if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
|
if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
|
||||||
if (handle) {
|
if (handle) {
|
||||||
|
|
|
@ -152,22 +152,6 @@ void ScreenManager::sendMessage(const char *msg, const char *value) {
|
||||||
stack_.back().screen->sendMessage(msg, 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 {
|
Screen *ScreenManager::topScreen() const {
|
||||||
if (!stack_.empty())
|
if (!stack_.empty())
|
||||||
return stack_.back().screen;
|
return stack_.back().screen;
|
||||||
|
|
|
@ -52,8 +52,6 @@ public:
|
||||||
virtual void preRender() {}
|
virtual void preRender() {}
|
||||||
virtual void render() {}
|
virtual void render() {}
|
||||||
virtual void postRender() {}
|
virtual void postRender() {}
|
||||||
virtual void deviceLost() {}
|
|
||||||
virtual void deviceRestore() {}
|
|
||||||
virtual void resized() {}
|
virtual void resized() {}
|
||||||
virtual void dialogFinished(const Screen *dialog, DialogResult result) {}
|
virtual void dialogFinished(const Screen *dialog, DialogResult result) {}
|
||||||
virtual bool touch(const TouchInput &touch) { return false; }
|
virtual bool touch(const TouchInput &touch) { return false; }
|
||||||
|
@ -115,8 +113,6 @@ public:
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
void resized();
|
void resized();
|
||||||
void deviceLost();
|
|
||||||
void deviceRestore();
|
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
// Push a dialog box in front. Currently 1-level only.
|
// Push a dialog box in front. Currently 1-level only.
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "gfx/gl_lost_manager.h"
|
|
||||||
|
|
||||||
#include "headless/SDLHeadlessHost.h"
|
#include "headless/SDLHeadlessHost.h"
|
||||||
|
|
||||||
|
@ -114,8 +113,6 @@ bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext *
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gl_lost_manager_init();
|
|
||||||
|
|
||||||
GraphicsContext *graphicsContext = new GLDummyGraphicsContext();
|
GraphicsContext *graphicsContext = new GLDummyGraphicsContext();
|
||||||
*ctx = graphicsContext;
|
*ctx = graphicsContext;
|
||||||
gfx_ = graphicsContext;
|
gfx_ = graphicsContext;
|
||||||
|
@ -134,8 +131,6 @@ void SDLHeadlessHost::ShutdownGraphics() {
|
||||||
glContext_ = nullptr;
|
glContext_ = nullptr;
|
||||||
SDL_DestroyWindow(screen_);
|
SDL_DestroyWindow(screen_);
|
||||||
screen_ = nullptr;
|
screen_ = nullptr;
|
||||||
|
|
||||||
gl_lost_manager_shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDLHeadlessHost::SwapBuffers() {
|
void SDLHeadlessHost::SwapBuffers() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue