Android OpenGL context loss handling.
This commit is contained in:
Родитель
35bec043ad
Коммит
8cc2a83e48
|
@ -152,6 +152,8 @@ public class SDLActivity extends Activity {
|
||||||
int action, float x,
|
int action, float x,
|
||||||
float y, float p);
|
float y, float p);
|
||||||
public static native void onNativeAccel(float x, float y, float z);
|
public static native void onNativeAccel(float x, float y, float z);
|
||||||
|
public static native void onNativeSurfaceDestroyed();
|
||||||
|
public static native void onNativeSurfaceCreated();
|
||||||
public static native void nativeRunAudioThread();
|
public static native void nativeRunAudioThread();
|
||||||
|
|
||||||
|
|
||||||
|
@ -453,8 +455,11 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||||
public void surfaceCreated(SurfaceHolder holder) {
|
public void surfaceCreated(SurfaceHolder holder) {
|
||||||
Log.v("SDL", "surfaceCreated()");
|
Log.v("SDL", "surfaceCreated()");
|
||||||
holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
|
holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
|
||||||
SDLActivity.createEGLSurface();
|
|
||||||
enableSensor(Sensor.TYPE_ACCELEROMETER, true);
|
enableSensor(Sensor.TYPE_ACCELEROMETER, true);
|
||||||
|
SDLActivity.onNativeSurfaceCreated();
|
||||||
|
|
||||||
|
// Note: we must not recreate the OpenGL context here, but wait for the application call initEGL() again
|
||||||
|
// from its own thread, to ensure the context is made current to the correct thread
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when we lose the surface
|
// Called when we lose the surface
|
||||||
|
@ -462,6 +467,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||||
Log.v("SDL", "surfaceDestroyed()");
|
Log.v("SDL", "surfaceDestroyed()");
|
||||||
SDLActivity.nativePause();
|
SDLActivity.nativePause();
|
||||||
enableSensor(Sensor.TYPE_ACCELEROMETER, false);
|
enableSensor(Sensor.TYPE_ACCELEROMETER, false);
|
||||||
|
SDLActivity.onNativeSurfaceDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the surface is resized
|
// Called when the surface is resized
|
||||||
|
|
|
@ -322,9 +322,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool vsync, bool
|
||||||
SDL_GL_SwapWindow(impl_->window_);
|
SDL_GL_SwapWindow(impl_->window_);
|
||||||
|
|
||||||
// Let GPU objects restore themselves
|
// Let GPU objects restore themselves
|
||||||
for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
|
Restore();
|
||||||
(*i)->OnDeviceReset();
|
|
||||||
|
|
||||||
CheckFeatureSupport();
|
CheckFeatureSupport();
|
||||||
|
|
||||||
if (multiSample > 1)
|
if (multiSample > 1)
|
||||||
|
@ -377,9 +375,9 @@ bool Graphics::TakeScreenShot(Image& destImage)
|
||||||
|
|
||||||
bool Graphics::BeginFrame()
|
bool Graphics::BeginFrame()
|
||||||
{
|
{
|
||||||
if (!IsInitialized())
|
if (!IsInitialized() || !impl_->context_)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If we should be fullscreen, but are not currently active, do not render
|
// If we should be fullscreen, but are not currently active, do not render
|
||||||
if (fullscreen_ && (SDL_GetWindowFlags(impl_->window_) & SDL_WINDOW_MINIMIZED))
|
if (fullscreen_ && (SDL_GetWindowFlags(impl_->window_) & SDL_WINDOW_MINIMIZED))
|
||||||
return false;
|
return false;
|
||||||
|
@ -524,7 +522,7 @@ void Graphics::Draw(PrimitiveType type, unsigned vertexStart, unsigned vertexCou
|
||||||
|
|
||||||
void Graphics::Draw(PrimitiveType type, unsigned indexStart, unsigned indexCount, unsigned minVertex, unsigned vertexCount)
|
void Graphics::Draw(PrimitiveType type, unsigned indexStart, unsigned indexCount, unsigned minVertex, unsigned vertexCount)
|
||||||
{
|
{
|
||||||
if (!indexCount || !indexBuffer_)
|
if (!indexCount || !indexBuffer_ || !indexBuffer_->GetGPUObject())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (impl_->fboDirty_)
|
if (impl_->fboDirty_)
|
||||||
|
@ -608,7 +606,7 @@ bool Graphics::SetVertexBuffers(const Vector<VertexBuffer*>& buffers, const PODV
|
||||||
elementMasks_[i] = elementMask;
|
elementMasks_[i] = elementMask;
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
if (!buffer)
|
if (!buffer || !buffer->GetGPUObject())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
|
glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
|
||||||
|
@ -695,7 +693,7 @@ bool Graphics::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers,
|
||||||
elementMasks_[i] = elementMask;
|
elementMasks_[i] = elementMask;
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
if (!buffer)
|
if (!buffer || !buffer->GetGPUObject())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
|
glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
|
||||||
|
@ -1744,29 +1742,13 @@ void Graphics::Release(bool clearGPUObjects, bool closeWindow)
|
||||||
|
|
||||||
if (clearGPUObjects)
|
if (clearGPUObjects)
|
||||||
{
|
{
|
||||||
// Shutting down: release all GPU objects that still exist, then delete the context
|
// Shutting down: release all GPU objects that still exist
|
||||||
for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
|
for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
|
||||||
(*i)->Release();
|
(*i)->Release();
|
||||||
gpuObjects_.Clear();
|
gpuObjects_.Clear();
|
||||||
|
|
||||||
if (impl_->context_)
|
|
||||||
{
|
|
||||||
MutexLock lock(GetStaticMutex());
|
|
||||||
SDL_GL_DeleteContext(impl_->context_);
|
|
||||||
impl_->context_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CleanupFramebuffers(true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (impl_->context_)
|
|
||||||
{
|
|
||||||
MutexLock lock(GetStaticMutex());
|
|
||||||
SDL_GL_DeleteContext(impl_->context_);
|
|
||||||
impl_->context_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are not shutting down, but recreating the context: mark GPU objects lost
|
// We are not shutting down, but recreating the context: mark GPU objects lost
|
||||||
for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
|
for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
|
||||||
(*i)->OnDeviceLost();
|
(*i)->OnDeviceLost();
|
||||||
|
@ -1776,9 +1758,13 @@ void Graphics::Release(bool clearGPUObjects, bool closeWindow)
|
||||||
depthTextures_.Clear();
|
depthTextures_.Clear();
|
||||||
shaderPrograms_.Clear();
|
shaderPrograms_.Clear();
|
||||||
|
|
||||||
// When the new context is initialized, it will have default state again
|
if (impl_->context_)
|
||||||
ResetCachedState();
|
{
|
||||||
ClearParameterSources();
|
MutexLock lock(GetStaticMutex());
|
||||||
|
|
||||||
|
SDL_GL_DeleteContext(impl_->context_);
|
||||||
|
impl_->context_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (closeWindow)
|
if (closeWindow)
|
||||||
{
|
{
|
||||||
|
@ -1790,6 +1776,24 @@ void Graphics::Release(bool clearGPUObjects, bool closeWindow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Graphics::Restore()
|
||||||
|
{
|
||||||
|
if (!impl_->window_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ensure first that the context exists
|
||||||
|
if (!impl_->context_)
|
||||||
|
impl_->context_ = SDL_GL_CreateContext(impl_->window_);
|
||||||
|
if (!impl_->context_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
|
||||||
|
(*i)->OnDeviceReset();
|
||||||
|
|
||||||
|
ResetCachedState();
|
||||||
|
ClearParameterSources();
|
||||||
|
}
|
||||||
|
|
||||||
void Graphics::CleanupRenderSurface(RenderSurface* surface)
|
void Graphics::CleanupRenderSurface(RenderSurface* surface)
|
||||||
{
|
{
|
||||||
if (!surface)
|
if (!surface)
|
||||||
|
|
|
@ -330,6 +330,8 @@ public:
|
||||||
void FreeScratchBuffer(void* buffer);
|
void FreeScratchBuffer(void* buffer);
|
||||||
/// Release/clear GPU objects and optionally close the window.
|
/// Release/clear GPU objects and optionally close the window.
|
||||||
void Release(bool clearGPUObjects, bool closeWindow);
|
void Release(bool clearGPUObjects, bool closeWindow);
|
||||||
|
/// Restore GPU objects and reinitialize state. Requires an open window.
|
||||||
|
void Restore();
|
||||||
/// Clean up a render surface from all FBOs.
|
/// Clean up a render surface from all FBOs.
|
||||||
void CleanupRenderSurface(RenderSurface* surface);
|
void CleanupRenderSurface(RenderSurface* surface);
|
||||||
|
|
||||||
|
|
|
@ -309,6 +309,11 @@ bool IndexBuffer::Create()
|
||||||
|
|
||||||
if (!object_)
|
if (!object_)
|
||||||
glGenBuffers(1, &object_);
|
glGenBuffers(1, &object_);
|
||||||
|
if (!object_)
|
||||||
|
{
|
||||||
|
LOGERROR("Failed to create index buffer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object_);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object_);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
|
||||||
|
|
|
@ -385,6 +385,11 @@ bool VertexBuffer::Create()
|
||||||
{
|
{
|
||||||
if (!object_)
|
if (!object_)
|
||||||
glGenBuffers(1, &object_);
|
glGenBuffers(1, &object_);
|
||||||
|
if (!object_)
|
||||||
|
{
|
||||||
|
LOGERROR("Failed to create vertex buffer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, object_);
|
glBindBuffer(GL_ARRAY_BUFFER, object_);
|
||||||
glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
|
||||||
|
|
|
@ -227,7 +227,7 @@ void Input::Update()
|
||||||
{
|
{
|
||||||
IntVector2 mousePos = GetCursorPosition();
|
IntVector2 mousePos = GetCursorPosition();
|
||||||
mouseMove_ = mousePos - lastCursorPosition_;
|
mouseMove_ = mousePos - lastCursorPosition_;
|
||||||
|
|
||||||
// Recenter the mouse cursor manually if it moved
|
// Recenter the mouse cursor manually if it moved
|
||||||
if (mouseMove_ != IntVector2::ZERO)
|
if (mouseMove_ != IntVector2::ZERO)
|
||||||
{
|
{
|
||||||
|
@ -847,6 +847,22 @@ void Input::HandleSDLEvent(void* sdlEvent)
|
||||||
if (input)
|
if (input)
|
||||||
input->GetSubsystem<Graphics>()->Close();
|
input->GetSubsystem<Graphics>()->Close();
|
||||||
}
|
}
|
||||||
|
#ifdef ANDROID
|
||||||
|
if (evt.window.event == SDL_WINDOWEVENT_SURFACE_LOST)
|
||||||
|
{
|
||||||
|
input = GetInputInstance(evt.window.windowID);
|
||||||
|
// Mark GPU objects lost
|
||||||
|
if (input)
|
||||||
|
input->graphics_->Release(false, false);
|
||||||
|
}
|
||||||
|
if (evt.window.event == SDL_WINDOWEVENT_SURFACE_CREATED)
|
||||||
|
{
|
||||||
|
input = GetInputInstance(evt.window.windowID);
|
||||||
|
// Restore GPU objects
|
||||||
|
if (input)
|
||||||
|
input->graphics_->Restore();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Modified by Lasse Öörni for Urho3D
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \file SDL_video.h
|
* \file SDL_video.h
|
||||||
*
|
*
|
||||||
|
@ -150,8 +152,10 @@ typedef enum
|
||||||
SDL_WINDOWEVENT_LEAVE, /**< Window has lost mouse focus */
|
SDL_WINDOWEVENT_LEAVE, /**< Window has lost mouse focus */
|
||||||
SDL_WINDOWEVENT_FOCUS_GAINED, /**< Window has gained keyboard focus */
|
SDL_WINDOWEVENT_FOCUS_GAINED, /**< Window has gained keyboard focus */
|
||||||
SDL_WINDOWEVENT_FOCUS_LOST, /**< Window has lost keyboard focus */
|
SDL_WINDOWEVENT_FOCUS_LOST, /**< Window has lost keyboard focus */
|
||||||
SDL_WINDOWEVENT_CLOSE /**< The window manager requests that the
|
SDL_WINDOWEVENT_CLOSE, /**< The window manager requests that the
|
||||||
window be closed */
|
window be closed */
|
||||||
|
SDL_WINDOWEVENT_SURFACE_LOST, /**< Android only: surface has been lost */
|
||||||
|
SDL_WINDOWEVENT_SURFACE_CREATED /**< Android only: surface has been restored after loss */
|
||||||
} SDL_WindowEventID;
|
} SDL_WindowEventID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -248,6 +248,23 @@ extern "C" void Java_org_libsdl_app_SDLActivity_nativeRunAudioThread(
|
||||||
Android_RunAudioThread();
|
Android_RunAudioThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Surface destroyed
|
||||||
|
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeSurfaceDestroyed(
|
||||||
|
JNIEnv* env, jclass cls)
|
||||||
|
{
|
||||||
|
if (Android_Window) {
|
||||||
|
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_SURFACE_LOST, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Surface created
|
||||||
|
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeSurfaceCreated(
|
||||||
|
JNIEnv* env, jclass cls)
|
||||||
|
{
|
||||||
|
if (Android_Window) {
|
||||||
|
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_SURFACE_CREATED, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Functions called by SDL into Java
|
Functions called by SDL into Java
|
||||||
|
|
Загрузка…
Ссылка в новой задаче