From 68af1b5bb0d002e1f843367d8dd11a07b3469e29 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 28 Nov 2014 11:54:56 -0800 Subject: [PATCH] Add support for render context lost/restored events, initially with support for WebGL (thanks @mrcdk) --- lime/app/Application.hx | 18 +++- lime/graphics/Renderer.hx | 128 ++++++++++++++++++++----- project/include/graphics/RenderEvent.h | 4 +- 3 files changed, 125 insertions(+), 25 deletions(-) diff --git a/lime/app/Application.hx b/lime/app/Application.hx index 5cf97f4e6..391b5a94e 100644 --- a/lime/app/Application.hx +++ b/lime/app/Application.hx @@ -105,6 +105,9 @@ class Application extends Module { TouchEventManager.onTouchMove.add (onTouchMove); TouchEventManager.onTouchEnd.add (onTouchEnd); + Renderer.onRenderContextLost.add (onRenderContextLost); + Renderer.onRenderContextRestored.add (onRenderContextRestored); + Window.onWindowActivate.add (onWindowActivate); Window.onWindowClose.add (onWindowClose); Window.onWindowDeactivate.add (onWindowDeactivate); @@ -295,6 +298,19 @@ class Application extends Module { public function onMouseWheel (deltaX:Float, deltaY:Float):Void { } + /** + * Called when a render context is lost + */ + public function onRenderContextLost ():Void { } + + + /** + * Called when a render context is restored + * @param context The current render context + */ + public function onRenderContextRestored (context:RenderContext):Void { } + + /** * Called when a touch end event is fired * @param x The current x coordinate of the touch point @@ -407,7 +423,7 @@ class Application extends Module { __eventInfo.deltaTime = 16; //TODO __dispatch (); - Renderer.dispatch (); + Renderer.render (); #if (js && html5) Browser.window.requestAnimationFrame (cast __triggerFrame); diff --git a/lime/graphics/Renderer.hx b/lime/graphics/Renderer.hx index 4b3383ada..b15460a1d 100644 --- a/lime/graphics/Renderer.hx +++ b/lime/graphics/Renderer.hx @@ -23,9 +23,11 @@ import flash.Lib; class Renderer { + public static var onRenderContextLost = new EventVoid> (); + public static var onRenderContextRestored = new EventVoid> (); public static var onRender = new EventVoid> (); - private static var eventInfo = new RenderEventInfo (); + private static var eventInfo = new RenderEventInfo (RENDER); private static var registered:Bool; public var context:RenderContext; @@ -44,6 +46,44 @@ class Renderer { public function create ():Void { + #if (cpp || neko || nodejs) + + handle = lime_renderer_create (window.handle); + + #end + + createContext (); + + #if (js && html5) + + switch (context) { + + case OPENGL (_): + + window.canvas.addEventListener ("webglcontextlost", handleCanvasEvent, false); + window.canvas.addEventListener ("webglcontextrestored", handleCanvasEvent, false); + + default: + + } + + #end + + if (!registered) { + + registered = true; + + #if (cpp || neko || nodejs) + lime_render_event_manager_register (dispatch, eventInfo); + #end + + } + + } + + + private function createContext ():Void { + #if (js && html5) if (window.div != null) { @@ -94,7 +134,6 @@ class Renderer { #elseif (cpp || neko || nodejs) - handle = lime_renderer_create (window.handle); context = OPENGL (new GLRenderContext ()); #elseif flash @@ -103,26 +142,14 @@ class Renderer { #end - if (!registered) { - - registered = true; - - #if (cpp || neko || nodejs) - lime_render_event_manager_register (dispatch, eventInfo); - #end - - } - } - private static function dispatch ():Void { + private function dispatch ():Void { - for (window in Application.__instance.windows) { + switch (eventInfo.type) { - if (window.currentRenderer != null) { - - var context = window.currentRenderer.context; + case RENDER: if (!Application.__initialized) { @@ -134,16 +161,22 @@ class Renderer { Application.__instance.render (context); onRender.dispatch (context); - window.currentRenderer.flip (); + flip (); - } + case RENDER_CONTEXT_LOST: + + context = null; + + onRenderContextLost.dispatch (); + + case RENDER_CONTEXT_RESTORED: + + createContext (); + + onRenderContextRestored.dispatch (context); } - #if (js && stats) - Application.__instance.windows[0].stats.end (); - #end - } @@ -156,6 +189,53 @@ class Renderer { } + #if (js && html5) + private function handleCanvasEvent (event:js.html.Event):Void { + + switch (event.type) { + + case "webglcontextlost": + + event.preventDefault (); + eventInfo.type = RENDER_CONTEXT_LOST; + dispatch (); + + case "webglcontextrestored": + + createContext (); + + eventInfo.type = RENDER_CONTEXT_RESTORED; + dispatch (); + + default: + + } + + } + #end + + + private static function render ():Void { + + eventInfo.type = RENDER; + + for (window in Application.__instance.windows) { + + if (window.currentRenderer != null) { + + window.currentRenderer.dispatch (); + + } + + } + + #if (js && stats) + Application.__instance.windows[0].stats.end (); + #end + + } + + #if (cpp || neko || nodejs) private static var lime_render_event_manager_register = System.load ("lime", "lime_render_event_manager_register", 2); private static var lime_renderer_create = System.load ("lime", "lime_renderer_create", 1); @@ -194,5 +274,7 @@ private class RenderEventInfo { @:enum private abstract RenderEventType(Int) { var RENDER = 0; + var RENDER_CONTEXT_LOST = 1; + var RENDER_CONTEXT_RESTORED = 2; } \ No newline at end of file diff --git a/project/include/graphics/RenderEvent.h b/project/include/graphics/RenderEvent.h index 526f0733a..1e761ef06 100644 --- a/project/include/graphics/RenderEvent.h +++ b/project/include/graphics/RenderEvent.h @@ -10,7 +10,9 @@ namespace lime { enum RenderEventType { - RENDER + RENDER, + RENDER_CONTEXT_LOST, + RENDER_CONTEXT_RESTORED };