commit dc10a48d3078980988dc9bf69ca727938b6aabac
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Fri Mar 31 17:24:38 2023 +0200

    Decouple (to a large degree) the OpenGL Library from Android.

diff --git a/src/main/java/org/distorted/examples/TableOfContents.java b/src/main/java/org/distorted/examples/TableOfContents.java
index 5e7bc3c..3207f65 100644
--- a/src/main/java/org/distorted/examples/TableOfContents.java
+++ b/src/main/java/org/distorted/examples/TableOfContents.java
@@ -88,8 +88,6 @@ public class TableOfContents extends ListActivity
 
   private enum Application
     {
-    FLATBLUR2         (R.drawable.icon_example_flatblur        , R.string.example_flatblur         , R.string.example_flatblur_subtitle         , FlatBlur2Activity.class ),
-
     MONALISA          (R.drawable.icon_example_monalisa        , R.string.example_monalisa        , R.string.example_monalisa_subtitle        ,         MonaLisaActivity.class),
     SINK              (R.drawable.icon_example_sink            , R.string.example_sink            , R.string.example_sink_subtitle            ,             SinkActivity.class),
     BEAN              (R.drawable.icon_example_bean            , R.string.example_bean            , R.string.example_bean_subtitle            ,             BeanActivity.class),
@@ -131,8 +129,7 @@ public class TableOfContents extends ListActivity
     DEFERREDJOB       (R.drawable.icon_example_deferredjob     , R.string.example_deferredjob           , R.string.example_deferredjob_subtitle           ,            DeferredJobActivity.class),
     SINGLEMESH        (R.drawable.icon_example_singlemesh      , R.string.example_singlemesh           , R.string.example_singlemesh_subtitle           ,            SingleMeshActivity.class),
     MESHFILE          (R.drawable.icon_example_meshfile        , R.string.example_meshfile           , R.string.example_meshfile_subtitle           ,            MeshFileActivity.class),
-    FLATBLUR          (R.drawable.icon_example_flatblur        , R.string.example_flatblur         , R.string.example_flatblur_subtitle         , FlatBlurActivity.class ),
-
+    FLATBLUR2         (R.drawable.icon_example_flatblur        , R.string.example_flatblur         , R.string.example_flatblur_subtitle         , FlatBlur2Activity.class ),
     ;
 
     final int icon, title, subtitle;
diff --git a/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java b/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
index e236a20..b20196a 100644
--- a/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
+++ b/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.aroundtheworld;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -48,24 +52,28 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class AroundTheWorldRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class AroundTheWorldRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
-   private GLSurfaceView mView;
-   private DistortedEffects mEffects;
+   private final GLSurfaceView mView;
+   private final Resources mResources;
+   private final DistortedEffects mEffects;
+   private final DistortedScreen mScreen;
+   private final AroundTheWorldEffectsManager mManager;
+   private final Static3D mScaleMatrix, mScaleVertex;
+
    private DistortedTexture mTexture;
-   private DistortedScreen mScreen;
    private MeshSquare mMesh;
-   private AroundTheWorldEffectsManager mManager;
-   private Static3D mScaleMatrix, mScaleVertex;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    AroundTheWorldRenderer(GLSurfaceView view)
       {
+      mView = view;
+      mResources = view.getResources();
+
       mScaleMatrix= new Static3D(1,1,1);
       mScaleVertex= new Static3D(1,1,1);
 
-      mView = view;
       mManager = new AroundTheWorldEffectsManager();
       mEffects = new DistortedEffects();
       mEffects.apply(new MatrixEffectScale(mScaleMatrix));
@@ -119,7 +127,7 @@ class AroundTheWorldRenderer implements GLSurfaceView.Renderer, DistortedLibrary
           {
           is.close();
           }
-        catch(IOException e) { }
+        catch(IOException ignored) { }
         }
 
       int objWidth = bitmap.getWidth();
@@ -145,7 +153,7 @@ class AroundTheWorldRenderer implements GLSurfaceView.Renderer, DistortedLibrary
       FragmentEffectChroma.enable();
       FragmentEffectContrast.enable();
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(),this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -154,4 +162,32 @@ class AroundTheWorldRenderer implements GLSurfaceView.Renderer, DistortedLibrary
       {
       android.util.Log.e("AroundTheWorld", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("AroundTheWorld", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/bean/BeanRenderer.java b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
index 6ad213d..7d17232 100644
--- a/src/main/java/org/distorted/examples/bean/BeanRenderer.java
+++ b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
@@ -38,20 +38,26 @@ import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class BeanRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class BeanRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
-   private GLSurfaceView mView;
-   private DistortedEffects mEffects;
-   private DistortedScreen mScreen;
-   private DistortedTexture mTexture;
+   private final GLSurfaceView mView;
+   private final Resources mResources;
+   private final DistortedEffects mEffects;
+   private final DistortedScreen mScreen;
+   private final DistortedTexture mTexture;
+   private final Static3D mScale;
+
    private MeshSquare mMesh;
-   private Static3D mScale;
    private float mBmpRatio;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -60,7 +66,8 @@ class BeanRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
    BeanRenderer(GLSurfaceView v)
       {
       mView = v;
-     
+      mResources = v.getResources();
+
       Static3D pointLeft  = new Static3D(-85/366.0f,  57/480.0f, 0);
       Static3D pointRight = new Static3D( 50/366.0f, 100/480.0f, 0);
       Static4D regionLeft = new Static4D( -3/366.0f,  33/480.0f, 0, 47/400.0f);
@@ -162,7 +169,7 @@ class BeanRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
 
      VertexEffectDistort.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -171,4 +178,32 @@ class BeanRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
      {
      android.util.Log.e("Bean", ex.getMessage() );
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Bean", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/blur/BlurRenderer.java b/src/main/java/org/distorted/examples/blur/BlurRenderer.java
index ae1d070..e12e2f1 100644
--- a/src/main/java/org/distorted/examples/blur/BlurRenderer.java
+++ b/src/main/java/org/distorted/examples/blur/BlurRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.blur;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -45,25 +49,29 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class BlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class BlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private final static int SIZE = 500;
     private final static float PART = 0.5f;
 
-    private GLSurfaceView mView;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedEffects mEffects, mBufferEffects;
+    private final DistortedScreen mScreen;
+    private final DistortedFramebuffer mBuffer;
+    private final MeshSquare mMesh, mMeshBuffer;
+    private final Static2D mHaloRadiusSta;
+    private final Static3D mMove, mScale, mBufferScale;
+
     private DistortedTexture mTexture;
-    private DistortedEffects mEffects, mBufferEffects;
-    private DistortedScreen mScreen;
-    private DistortedFramebuffer mBuffer;
-    private MeshSquare mMesh, mMeshBuffer;
-    private Static2D mHaloRadiusSta;
-    private Static3D mMove, mScale, mBufferScale;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    BlurRenderer(GLSurfaceView v)
       {
-      mView       = v;
+      mView = v;
+      mResources = v.getResources();
+
       mMesh       = new MeshSquare(1,1);
       mMeshBuffer = new MeshSquare(1,1);
       mScreen     = new DistortedScreen();
@@ -156,7 +164,7 @@ class BlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
          {
          is.close();
          }
-       catch(IOException e) { }
+       catch(IOException ignored) { }
        }
 
      if( mTexture==null ) mTexture = new DistortedTexture();
@@ -170,7 +178,7 @@ class BlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
 
      PostprocessEffectBlur.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(),this);
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -179,4 +187,32 @@ class BlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
      {
      android.util.Log.e("Blur", ex.getMessage() );
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+     {
+     Context context = mView.getContext();
+     final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+     final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+     int glESversion = configurationInfo.reqGlEsVersion;
+     int major = glESversion >> 16;
+     int minor = glESversion & 0xff;
+
+     return 100*major + 10*minor;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+     {
+     return mResources.openRawResource(fileID);
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+     {
+     android.util.Log.e("Blur", message );
+     }
 }
diff --git a/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java b/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
index 9a869f1..b80cf31 100644
--- a/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
+++ b/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
@@ -42,18 +42,24 @@ import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class CatAndDogRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class CatAndDogRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
-    private GLSurfaceView mView;
-    private DistortedTexture mTexture;
-    private DistortedScreen mScreen;
-    private Static3D mScaleStart, mScaleEnd, mMoveStart, mMoveEnd;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedTexture mTexture;
+    private final DistortedScreen mScreen;
+    private final Static3D mScaleStart, mScaleEnd, mMoveStart, mMoveEnd;
+
     private float mBmpRatio;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -64,6 +70,7 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
       final int DURATION_MATRIX_EFFECTS = 10000;
 
       mView = v;
+      mResources = v.getResources();
 
       DistortedEffects effects = new DistortedEffects();
 
@@ -114,7 +121,7 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
       {
       final float SCALE_START = 0.3f;
       final float SCALE_END   = 0.6f;
-      float min= (width>height ? height : width);
+      float min= (Math.min(width,height));
 
       mScaleStart.set( SCALE_START*min, SCALE_START*min*mBmpRatio, 1 );
       mScaleEnd  .set( SCALE_END  *min, SCALE_END  *min*mBmpRatio, 1 );
@@ -149,7 +156,7 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
           {
           is.close();
           } 
-        catch(IOException e) { }
+        catch(IOException ignored) { }
         }  
       
       mBmpRatio = (float)bitmap.getHeight()/bitmap.getWidth();
@@ -158,7 +165,7 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
       FragmentEffectChroma.enable();
       FragmentEffectAlpha.enable();
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(),this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -167,4 +174,32 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
       {
       android.util.Log.e("CatAndDog", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("CatAndDog", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/check/CheckRenderer.java b/src/main/java/org/distorted/examples/check/CheckRenderer.java
index 8d4c3d6..90d641a 100644
--- a/src/main/java/org/distorted/examples/check/CheckRenderer.java
+++ b/src/main/java/org/distorted/examples/check/CheckRenderer.java
@@ -44,9 +44,12 @@ import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 import org.distorted.library.type.Dynamic1D;
 
+import android.app.ActivityManager;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLES31;
@@ -55,25 +58,28 @@ import android.util.Log;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class CheckRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class CheckRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private static String compilationResult;
     private static String compilationTitle;
 
-    private GLSurfaceView mView;
-    private DistortedEffects mEffects;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedEffects mEffects;
+    private final DistortedScreen mScreen;
+    private final Static3D mScaleMatrix, mScaleVertex, mSwirl1, mSwirl2, mDeform1, mDeform2;
+    private final Static1D mRadius;
+
     private DistortedTexture mTexture;
     private MeshSquare mMesh;
-    private DistortedScreen mScreen;
     private int mObjHeight, mObjWidth;
-    private Static3D mScaleMatrix, mScaleVertex, mSwirl1, mSwirl2, mDeform1, mDeform2;
-    private Static1D mRadius;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     CheckRenderer(GLSurfaceView view)
       { 
       mView = view;
+      mResources = view.getResources();
 
       CheckActivity act = (CheckActivity)mView.getContext();
 
@@ -180,7 +186,7 @@ class CheckRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exceptio
           {
           is.close();
           } 
-        catch(IOException e) { }
+        catch(IOException ignored) { }
         }
 
       mObjHeight = bitmap.getHeight();
@@ -201,7 +207,7 @@ class CheckRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exceptio
       mDeform1.set(           0,          0, 0);
       mDeform2.set(           0, mObjHeight, 0);
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(),this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
     
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -252,4 +258,32 @@ class CheckRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exceptio
           }
         });
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+      {
+      android.util.Log.e("Check", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/deferredjob/DeferredJobRenderer.java b/src/main/java/org/distorted/examples/deferredjob/DeferredJobRenderer.java
index 2dee40f..a6ae4ec 100644
--- a/src/main/java/org/distorted/examples/deferredjob/DeferredJobRenderer.java
+++ b/src/main/java/org/distorted/examples/deferredjob/DeferredJobRenderer.java
@@ -19,12 +19,15 @@
 
 package org.distorted.examples.deferredjob;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.opengl.GLSurfaceView;
 
-import org.distorted.library.effect.EffectType;
 import org.distorted.library.effect.MatrixEffectMove;
 import org.distorted.library.effect.MatrixEffectQuaternion;
 import org.distorted.library.effect.MatrixEffectScale;
@@ -43,22 +46,26 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import java.io.InputStream;
+
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class DeferredJobRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class DeferredJobRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
-    private GLSurfaceView mView;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedScreen mScreen;
+    private final DistortedEffects mEffects;
+    private final Static3D mScale;
+    private final VertexEffectRotate mRotate;
+    private final Dynamic1D mAngleDyn;
+    private final Static1D mAngle;
+
     private DistortedTexture mTexture;
-    private DistortedScreen mScreen;
-    private DistortedEffects mEffects;
-    private Static3D mScale;
     private MeshBase mMesh;
-    private VertexEffectRotate mRotate;
-    private Dynamic1D mAngleDyn;
-    private Static1D mAngle;
 
     Static4D mQuat1, mQuat2;
     int mScreenMin;
@@ -68,6 +75,8 @@ class DeferredJobRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Ex
     DeferredJobRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
+
       mScreen = new DistortedScreen();
       mScale= new Static3D(1,1,1);
       Static3D center=new Static3D(0,0,0);
@@ -134,14 +143,7 @@ class DeferredJobRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Ex
 
       VertexEffectRotate.enable();
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(),this);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void distortedException(Exception ex)
-      {
-      android.util.Log.e("DeferredJob", ex.getMessage() );
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -260,4 +262,38 @@ class DeferredJobRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Ex
       return result;
       }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void distortedException(Exception ex)
+      {
+      android.util.Log.e("DeferredJob", ex.getMessage() );
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("DeferredJob", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/deform/DeformRenderer.java b/src/main/java/org/distorted/examples/deform/DeformRenderer.java
index 9891d58..9172336 100644
--- a/src/main/java/org/distorted/examples/deform/DeformRenderer.java
+++ b/src/main/java/org/distorted/examples/deform/DeformRenderer.java
@@ -40,50 +40,52 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Paint.Style;
 import android.opengl.GLSurfaceView;
 
+import java.io.InputStream;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class DeformRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.ExceptionListener
+class DeformRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.LibraryUser
    {
    private static final int NUM_VECTORS =  8;
    private static final int NUM_LINES   = 10;
    private static final float QUOT      = 0.6f;
 
-   private GLSurfaceView mView;
-   private DistortedTexture mTexture;
-   private DistortedEffects mEffects;
-   private MeshBase mMesh;
-   private DistortedScreen mScreen;
-   private Static3D mTouchPoint, mScale;
-
-   private Static3D[] vDistort;
-   private Static3D[] vDeform;
-   private Static3D[] vShear;
+   private final GLSurfaceView mView;
+   private final Resources mResources;
+   private final DistortedTexture mTexture;
+   private final DistortedEffects mEffects;
+   private final DistortedScreen mScreen;
+   private final Static3D mTouchPoint, mScale;
+   private final Static3D[] vDistort, vDeform, vShear;
+   private final Static4D mRegion;
+   private final MatrixEffectShear mMovingShear, mReleasedShear;
+   private final VertexEffectDistort mMovingDistort, mReleasedDistort;
+   private final VertexEffectDeform mMovingDeform, mReleasedDeform;
+   private final Dynamic3D mReleasedDistortDynamic, mReleasedDeformDynamic, mReleasedShearDynamic;
 
-   private Static4D mRegion;
+   private MeshBase mMesh;
+   private EffectName mMode = EffectName.DISTORT;
    private int scrHeight, scrWidth;
    private int textureWidth, textureHeight;
    private float mRadius;
-
-   private EffectName mMode = EffectName.DISTORT;
    private long mLastEffect = -1;
 
-   private MatrixEffectShear mMovingShear, mReleasedShear;
-   private VertexEffectDistort mMovingDistort, mReleasedDistort;
-   private VertexEffectDeform mMovingDeform, mReleasedDeform;
-
-   private Dynamic3D mReleasedDistortDynamic, mReleasedDeformDynamic, mReleasedShearDynamic;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    DeformRenderer(GLSurfaceView view)
       { 
       mView = view;
+      mResources = view.getResources();
 
       mTexture    = new DistortedTexture();
       mEffects    = new DistortedEffects();
@@ -233,14 +235,7 @@ class DeformRenderer implements GLSurfaceView.Renderer, EffectListener, Distorte
      VertexEffectDistort.enable();
      VertexEffectDeform.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(),this);
-     }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   public void distortedException(Exception ex)
-     {
-     android.util.Log.e("Deform", ex.getMessage() );
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -327,4 +322,39 @@ class DeformRenderer implements GLSurfaceView.Renderer, EffectListener, Distorte
                      break;
        }
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void distortedException(Exception ex)
+     {
+     android.util.Log.e("Deform", ex.getMessage() );
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+      {
+      android.util.Log.e("Deform", message );
+      }
    }
diff --git a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
index 462aeb8..dc376d2 100644
--- a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
+++ b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
@@ -42,31 +42,37 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class DifferentBitmapsRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class DifferentBitmapsRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
    private static final int[] bitmap = { R.raw.dog, R.raw.face, R.raw.cat };
    private static final int NUM = bitmap.length;
    
-   private GLSurfaceView mView;
-   private DistortedEffects[] mEffects;
+   private final GLSurfaceView mView;
+   private final DistortedEffects[] mEffects;
+   private final DistortedScreen mScreen;
+   private final Static3D mScaleMatrix, mScaleVertex;
+   private final Static3D[] mMove;
+   private final Resources mResources;
    private DistortedTexture[] mTexture;
    private MeshSquare mMesh;
-   private DistortedScreen mScreen;
-   private Static3D mScaleMatrix, mScaleVertex;
-   private Static3D[] mMove;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    DifferentBitmapsRenderer(GLSurfaceView v)
       {     
       mView = v;
-     
+      mResources = v.getResources();
+
       Dynamic3D dDistort = new Dynamic3D(3000,0.0f);
       dDistort.add(new Static3D( 25,0,0));
       dDistort.add(new Static3D(-25,0,0));
@@ -168,14 +174,7 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer, DistortedLibra
      VertexEffectSink.enable();
      VertexEffectDistort.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(),this);
-     }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   public void distortedException(Exception ex)
-     {
-     android.util.Log.e("DifferentBitmaps", ex.getMessage() );
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -195,10 +194,44 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer, DistortedLibra
          {
          is.close();
          }
-       catch(IOException e) { }
+       catch(IOException ignored) { }
        }
 
      return bitmap;
      }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void distortedException(Exception ex)
+     {
+     android.util.Log.e("DifferentBitmaps", ex.getMessage() );
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+     {
+     Context context = mView.getContext();
+     final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+     final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+     int glESversion = configurationInfo.reqGlEsVersion;
+     int major = glESversion >> 16;
+     int minor = glESversion & 0xff;
+
+     return 100*major + 10*minor;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+     {
+     return mResources.openRawResource(fileID);
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+     {
+     android.util.Log.e("DifferentBitmaps", message );
+     }
 }
diff --git a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
index 5b8888c..be4c625 100644
--- a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
+++ b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
@@ -44,23 +44,29 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class DifferentEffectsRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class DifferentEffectsRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
    private static final int NUM = 3;
    
-   private GLSurfaceView mView;
-   private DistortedEffects[] mEffects;
+   private final GLSurfaceView mView;
+   private final Resources mResources;
+   private final DistortedEffects[] mEffects;
+   private final DistortedScreen mScreen;
+   private final Static3D mScale, mScaleBitmap;
+   private final Static3D[] mMove;
+
    private DistortedTexture mTexture;
    private MeshSquare mMesh;
-   private DistortedScreen mScreen;
-   private Static3D mScale, mScaleBitmap;
-   private Static3D[] mMove;
    private int mBmpWidth, mBmpHeight;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -68,7 +74,8 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer, DistortedLibra
    DifferentEffectsRenderer(GLSurfaceView v)
       {     
       mView = v;
-      
+      mResources = v.getResources();
+
       // mEffects[0] effects
       Static3D pLeft = new Static3D(214 - 594/2, 394 - 600/2, 0);
       Static3D pRight= new Static3D(390 - 594/2, 388 - 600/2, 0);
@@ -188,7 +195,7 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer, DistortedLibra
      VertexEffectDistort.enable();
      FragmentEffectChroma.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -197,4 +204,32 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer, DistortedLibra
      {
      android.util.Log.e("DifferentEffects", ex.getMessage() );
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+      {
+      android.util.Log.e("DifferentEffects", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java b/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
index 2004b3d..620bf25 100644
--- a/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
+++ b/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
@@ -22,6 +22,10 @@ package org.distorted.examples.dynamic;
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -36,32 +40,39 @@ import org.distorted.library.main.DistortedTexture;
 import org.distorted.library.main.DistortedLibrary;
 import org.distorted.library.type.Static3D;
 
+import java.io.InputStream;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class DynamicRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class DynamicRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
    {  
-   private DynamicSurfaceView mView;
-   private DistortedTexture mTexture;
-   private DistortedEffects mEffects;
-   private DistortedScreen mScreen;
-   private MeshSquare mMesh;
+   private final DynamicSurfaceView mView;
+   private final Resources mResources;
+   private final DistortedTexture mTexture;
+   private final DistortedEffects mEffects;
+   private final DistortedScreen mScreen;
+   private final MeshSquare mMesh;
+   private final Paint mPaint;
+   private final Static3D mScale;
+
    private Canvas mCanvas;
    private Bitmap mBitmap;
-   private Paint mPaint;
-   private Static3D mScale;
+
    private static int texW, texH;
     
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    DynamicRenderer(DynamicSurfaceView v)
-     {    
+     {
+     mView = v;
+     mResources = v.getResources();
+
      mPaint = new Paint();
      mPaint.setAntiAlias(true);
      mPaint.setFakeBoldText(true);
      mPaint.setColor(0xff447da7);
      mPaint.setStyle(Style.FILL);
-      
-     mView    = v;
+
      mMesh    = new MeshSquare(1,1);
      mScreen  = new DistortedScreen();
      mEffects = new DistortedEffects();
@@ -106,7 +117,7 @@ class DynamicRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
 
    public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
      {
-     DistortedLibrary.onSurfaceCreated(mView.getContext(),this);
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -115,4 +126,32 @@ class DynamicRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
      {
      android.util.Log.e("Dynamic", ex.getMessage() );
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+      {
+      android.util.Log.e("Dynamic", message );
+      }
   }
diff --git a/src/main/java/org/distorted/examples/earth/EarthRenderer.java b/src/main/java/org/distorted/examples/earth/EarthRenderer.java
index 892a4c2..8dfb47e 100644
--- a/src/main/java/org/distorted/examples/earth/EarthRenderer.java
+++ b/src/main/java/org/distorted/examples/earth/EarthRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.earth;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -62,7 +66,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class EarthRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class EarthRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private static final float RADIUS_V= 1.0f/ 8;
     private static final float RADIUS_F= 1.0f/15;
@@ -71,24 +75,20 @@ class EarthRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exceptio
     private static final float NEAR    =    0.1f;
     private static final float SCALE   =   1.10f;
 
-    private GLSurfaceView mView;
-    private DistortedTexture mTexture;
-    private DistortedEffects mEffects;
-    private MeshBase mMesh;
-    private DistortedScreen mScreen;
-    private float mObjWidth, mObjHeight, mObjDepth;
-    private Static3D mMove, mScaleFactor;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedTexture mTexture;
+    private final DistortedEffects mEffects;
+    private final MeshBase mMesh;
+    private final DistortedScreen mScreen;
+    private final Static1D mStrength, mSwirl;
+    private final Static3D mMove, mScaleFactor, mColor,mRegionF,mPinch;
+    private final Static4D mRegionV;
+    private final float mObjWidth, mObjHeight, mObjDepth;
 
     private int mScrWidth, mScrHeight;
     private float mLevel;
 
-    private Static3D mColor;
-    private Static3D mRegionF;
-    private Static4D mRegionV;
-    private Static1D mStrength;
-    private Static3D mPinch;
-    private Static1D mSwirl;
-
     Static4D mQuat1, mQuat2;
     int mScreenMin;
 
@@ -97,6 +97,7 @@ class EarthRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exceptio
     EarthRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
 
       mLevel = SCALE;
 
@@ -204,9 +205,9 @@ class EarthRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exceptio
 
       switch(name)
         {
-        case DISTORT          : vector = new Static3D( +x*mObjWidth/CORR, +y*mObjHeight/CORR, +z*mObjDepth/CORR);
+        case DISTORT          : vector = new Static3D( x*mObjWidth/CORR, y*mObjHeight/CORR, z*mObjDepth/CORR);
                                 effect = new VertexEffectDistort(   vector, center, mRegionV); break;
-        case DEFORM           : vector = new Static3D( +x*mObjWidth/CORR, +y*mObjHeight/CORR, +z*mObjDepth/CORR);
+        case DEFORM           : vector = new Static3D( x*mObjWidth/CORR, y*mObjHeight/CORR, z*mObjDepth/CORR);
                                 Static1D radius = new Static1D(mObjWidth/2);
                                 effect = new VertexEffectDeform (   vector, radius, center, mRegionV); break;
         case SINK             : effect = new VertexEffectSink   (mStrength, center, mRegionV); break;
@@ -232,7 +233,7 @@ class EarthRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exceptio
         case CONTRAST         : effect = new FragmentEffectContrast  (mStrength,        center, mRegionF, false); break;
         case SMOOTH_CONTRAST  : effect = new FragmentEffectContrast  (mStrength,        center, mRegionF, true ); break;
 
-        default               : android.util.Log.e("EarthRenderer", "unexpected effect: "+name.toString() );
+        default               : android.util.Log.e("EarthRenderer", "unexpected effect: "+name );
         }
 
       if( effect!=null )
@@ -276,10 +277,8 @@ class EarthRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exceptio
 
       Effect.enableEffects(EffectType.FRAGMENT);
       Effect.enableEffects(EffectType.VERTEX);
-
       DistortedLibrary.setMax(EffectType.FRAGMENT, 20);
-
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -288,4 +287,32 @@ class EarthRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exceptio
       {
       android.util.Log.e("Earth", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Earth", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java b/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
index 8fa77fb..d2fe7a3 100644
--- a/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
+++ b/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
@@ -22,6 +22,10 @@ package org.distorted.examples.effectqueue;
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -42,36 +46,39 @@ import org.distorted.library.main.DistortedTexture;
 import org.distorted.library.message.EffectListener;
 import org.distorted.library.type.Static3D;
 
+import java.io.InputStream;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.ExceptionListener
+class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.LibraryUser
   {
   private static final int NUMLINES =  10;
   private static final int MESH_QUALITY = 100;
   static final int BWID = 600;
   static final int BHEI = 600;
-   
-  private EffectQueueSurfaceView mView;
-  private Paint mPaint;
-  private int texWidth, texHeight;
-  private Static3D mScale;
 
-  private DistortedTexture mTexture;
-  private MeshSquare mMesh;
-  private DistortedEffects mEffects;
-  private DistortedScreen mScreen;
+  private final EffectQueueSurfaceView mView;
+  private final Resources mResources;
+  private final DistortedTexture mTexture;
+  private final MeshSquare mMesh;
+  private final DistortedEffects mEffects;
+  private final DistortedScreen mScreen;
+  private final Paint mPaint;
+  private final Static3D mScale;
+  private final int texWidth, texHeight;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   EffectQueueRenderer(EffectQueueSurfaceView v)
-    {    
+    {
+    mView = v;
+    mResources = v.getResources();
+
     mPaint = new Paint();
     mPaint.setAntiAlias(true);
     mPaint.setFakeBoldText(true);
     mPaint.setStyle(Style.FILL);
-      
-    mView = v;
-      
+
     texWidth = BWID;
     texHeight= BHEI;
     mScale = new Static3D(1,1,1);
@@ -141,7 +148,15 @@ class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListener, Dis
     FragmentEffectChroma.enable();
     FragmentEffectSaturation.enable();
 
-    DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+    DistortedLibrary.onSurfaceCreated(this);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void effectFinished(final long effectID)
+    {
+    EffectQueueActivity act = (EffectQueueActivity)mView.getContext();
+    act.effectFinished(effectID);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -153,9 +168,29 @@ class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListener, Dis
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void effectFinished(final long effectID)
+  public int openGlVersion()
     {
-    EffectQueueActivity act = (EffectQueueActivity)mView.getContext();
-    act.effectFinished(effectID);
+    Context context = mView.getContext();
+    final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+    final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+    int glESversion = configurationInfo.reqGlEsVersion;
+    int major = glESversion >> 16;
+    int minor = glESversion & 0xff;
+
+    return 100*major + 10*minor;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public InputStream localFile(int fileID)
+    {
+    return mResources.openRawResource(fileID);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void logMessage(String message)
+    {
+    android.util.Log.e("EffectQueue", message );
     }
   }
diff --git a/src/main/java/org/distorted/examples/flag/FlagRenderer.java b/src/main/java/org/distorted/examples/flag/FlagRenderer.java
index ba95a2d..d4975e6 100644
--- a/src/main/java/org/distorted/examples/flag/FlagRenderer.java
+++ b/src/main/java/org/distorted/examples/flag/FlagRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.flag;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -47,15 +51,16 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class FlagRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class FlagRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
-    private GLSurfaceView mView;
-    private DistortedTexture mTexture;
-    private DistortedScreen mScreen;
-    private Dynamic5D mWaveDyn;
-    private Static5D mWaveSta1, mWaveSta2;
-    private int mObjWidth, mObjHeight, mObjDepth;
-    private Static3D mScale;
+    private final GLSurfaceView mView;
+    private final DistortedTexture mTexture;
+    private final DistortedScreen mScreen;
+    private final Dynamic5D mWaveDyn;
+    private final Static5D mWaveSta1, mWaveSta2;
+    private final int mObjWidth, mObjHeight, mObjDepth;
+    private final Static3D mScale;
+    private final Resources mResources;
 
     Static4D mQuat1, mQuat2;
     int mScreenMin;
@@ -65,6 +70,7 @@ class FlagRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
     FlagRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
 
       final int GRIDX = 50;
       final int GRIDY = 30;
@@ -191,7 +197,7 @@ class FlagRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
       VertexEffectScale.enable();
       VertexEffectWave.enable();
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -200,4 +206,32 @@ class FlagRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
       {
       android.util.Log.e("Flag", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Flag", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/flatblur/FlatBlurRenderer.java b/src/main/java/org/distorted/examples/flatblur/FlatBlurRenderer.java
index 57caa80..6504bb9 100644
--- a/src/main/java/org/distorted/examples/flatblur/FlatBlurRenderer.java
+++ b/src/main/java/org/distorted/examples/flatblur/FlatBlurRenderer.java
@@ -19,19 +19,26 @@
 
 package org.distorted.examples.flatblur;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.opengl.GLSurfaceView;
 
 import org.distorted.library.main.DistortedLibrary;
 import org.distorted.library.main.DistortedScreen;
 
+import java.io.InputStream;
+
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class FlatBlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class FlatBlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private final GLSurfaceView mView;
+    private final Resources mResources;
     private final DistortedScreen mScreen;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -39,6 +46,7 @@ class FlatBlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
     FlatBlurRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
       mScreen = new DistortedScreen();
       }
 
@@ -61,7 +69,22 @@ class FlatBlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
     public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
       {
       OverlayStars.enableEffects();
-      DistortedLibrary.onSurfaceCreated( mView.getContext(), this);
+      DistortedLibrary.onSurfaceCreated(this);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void button1()
+      {
+      OverlayStars stars = new OverlayStars();
+      stars.startOverlay(mScreen);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void button2()
+      {
+
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -73,16 +96,29 @@ class FlatBlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public void button1()
+    public int openGlVersion()
       {
-      OverlayStars stars = new OverlayStars();
-      stars.startOverlay(mScreen);
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public void button2()
+    public InputStream localFile(int fileID)
       {
+      return mResources.openRawResource(fileID);
+      }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Blur", message );
       }
 }
diff --git a/src/main/java/org/distorted/examples/flatblur2/FlatBlur2Renderer.java b/src/main/java/org/distorted/examples/flatblur2/FlatBlur2Renderer.java
index 28cdb93..372e5bc 100644
--- a/src/main/java/org/distorted/examples/flatblur2/FlatBlur2Renderer.java
+++ b/src/main/java/org/distorted/examples/flatblur2/FlatBlur2Renderer.java
@@ -19,6 +19,9 @@
 
 package org.distorted.examples.flatblur2;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -55,9 +58,10 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class FlatBlur2Renderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener, ListenerOverlay, EffectListener
+class FlatBlur2Renderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser, ListenerOverlay, EffectListener
 {
     private final GLSurfaceView mView;
+    private final Resources mResources;
     private final DistortedScreen mScreen;
     private Static3D mScale1, mScale2, mMove;
     private DistortedNode mNode;
@@ -68,6 +72,7 @@ class FlatBlur2Renderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
     FlatBlur2Renderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
       mScreen = new DistortedScreen();
       }
 
@@ -151,14 +156,7 @@ class FlatBlur2Renderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
       effects.apply((mv));
 
       OverlayStars.enableEffects();
-      DistortedLibrary.onSurfaceCreated( mView.getContext(), this);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void distortedException(Exception ex)
-      {
-      android.util.Log.e("FlatBlur2", ex.getMessage() );
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -186,7 +184,7 @@ class FlatBlur2Renderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-   private PostprocessEffectGlow constructGlow()
+    private PostprocessEffectGlow constructGlow()
       {
       final int DUR_GLO = 3000;
       Dynamic2D haloRadius = new Dynamic2D(DUR_GLO,0.5f);
@@ -223,4 +221,39 @@ class FlatBlur2Renderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
       DistortedEffects effects = mNode.getEffects();
       effects.abortByType(EffectType.POSTPROCESS);
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void distortedException(Exception ex)
+      {
+      android.util.Log.e("FlatBlur2", ex.getMessage() );
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("FlatBlur2", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/generic/GenericRenderer.java b/src/main/java/org/distorted/examples/generic/GenericRenderer.java
index 8500ecd..0ddabd7 100644
--- a/src/main/java/org/distorted/examples/generic/GenericRenderer.java
+++ b/src/main/java/org/distorted/examples/generic/GenericRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.generic;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -49,12 +53,13 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class GenericRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class GenericRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private static final float FOV = 30.0f;
     private static final float NEAR = 0.1f;
 
     private final GLSurfaceView mView;
+    private final Resources mResources;
     private final DistortedTexture mObjectTexture, mBackgroundTexture, mCenterTexture, mRegionTexture;
     private final DistortedEffects mObjectEffects;
     private final DistortedScreen mScreen;
@@ -76,6 +81,7 @@ class GenericRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
     GenericRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
 
       GenericActivity2 act = (GenericActivity2)v.getContext();
 
@@ -320,7 +326,7 @@ class GenericRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
       Effect.enableEffects(EffectType.POSTPROCESS);
 
       DistortedLibrary.needTransformFeedback();
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -329,4 +335,32 @@ class GenericRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
       {
       android.util.Log.e("Generic", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+      {
+      android.util.Log.e("Generic", message );
+      }
 }
\ No newline at end of file
diff --git a/src/main/java/org/distorted/examples/girl/GirlRenderer.java b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
index f733a56..ca25893 100644
--- a/src/main/java/org/distorted/examples/girl/GirlRenderer.java
+++ b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
@@ -27,7 +27,6 @@ import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.examples.R;
 
-import org.distorted.library.effect.EffectType;
 import org.distorted.library.effect.MatrixEffectScale;
 import org.distorted.library.effect.VertexEffectDistort;
 import org.distorted.library.effect.VertexEffectScale;
@@ -44,22 +43,28 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class GirlRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class GirlRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
-    private GLSurfaceView mView;
-    private DistortedEffects mEffects;
-    private DistortedScreen mScreen;
-    private DistortedTexture mTexture;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedEffects mEffects;
+    private final DistortedScreen mScreen;
+    private final DistortedTexture mTexture;
+    private final Static3D v0,v1,v2,v3;
+    private final Static1D dBegin, dMiddle, dEnd, s0;
+    private final Static3D mScaleMatrix, mScaleVertex;
+
     private MeshSquare mMesh;
-    private Static3D v0,v1,v2,v3;
-    private Static1D dBegin, dMiddle, dEnd, s0;
-    private Static3D mScaleMatrix, mScaleVertex;
     private float mBmpRatio;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -68,6 +73,7 @@ class GirlRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
    GirlRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
 
       Static3D pLeft = new Static3D(-68/400.0f, 36/400.0f, 0);
       Static3D pRight= new Static3D( 47/400.0f, 36/400.0f, 0);
@@ -192,7 +198,7 @@ class GirlRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
          {
          is.close();
          }
-       catch(IOException e) { }
+       catch(IOException ignored) { }
        }
       
      mBmpRatio = (float)bitmap.getHeight()/bitmap.getWidth();
@@ -210,7 +216,7 @@ class GirlRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
      VertexEffectSink.enable();
      VertexEffectSwirl.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -219,4 +225,32 @@ class GirlRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
      {
      android.util.Log.e("Girl", ex.getMessage() );
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+      {
+      android.util.Log.e("Girl", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/glow/GlowRenderer.java b/src/main/java/org/distorted/examples/glow/GlowRenderer.java
index ad37b41..0fed3fd 100644
--- a/src/main/java/org/distorted/examples/glow/GlowRenderer.java
+++ b/src/main/java/org/distorted/examples/glow/GlowRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.glow;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -44,11 +48,12 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class GlowRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class GlowRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
    private static final float HALO_TO_RADIUS = 0.2f;
 
    private final GLSurfaceView mView;
+   private final Resources mResources;
    private final DistortedTexture mLeaf;
    private final DistortedScreen mScreen;
    private final PostprocessEffectGlow mGlow;
@@ -61,6 +66,7 @@ class GlowRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
    GlowRenderer(GLSurfaceView v)
       {     
       mView = v;
+      mResources = v.getResources();
 
       mLeaf      = new DistortedTexture();
       mScale     = new Static3D(1,1,1);
@@ -147,7 +153,7 @@ class GlowRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
 
      PostprocessEffectGlow.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -156,4 +162,32 @@ class GlowRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
      {
      android.util.Log.e("Glow", ex.getMessage() );
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+      {
+      android.util.Log.e("Glow", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/inflate/InflateRenderer.java b/src/main/java/org/distorted/examples/inflate/InflateRenderer.java
index b9c2160..6fc1a7d 100644
--- a/src/main/java/org/distorted/examples/inflate/InflateRenderer.java
+++ b/src/main/java/org/distorted/examples/inflate/InflateRenderer.java
@@ -36,23 +36,30 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static4D;
 import org.distorted.library.type.Static3D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.opengl.GLSurfaceView;
 
+import java.io.InputStream;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class InflateRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class InflateRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private static final float FOV = 30.0f;
     private static final float NEAR = 0.1f;
 
-    private GLSurfaceView mView;
-    private DistortedTexture mTexture;
-    private DistortedEffects mEffects;
-    private MeshBase mMesh;
-    private DistortedScreen mScreen;
-    private float mObjWidth, mObjHeight, mObjDepth;
-    private Static3D mScale;
-    private Static1D mAlpha;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedTexture mTexture;
+    private final DistortedEffects mEffects;
+    private final MeshBase mMesh;
+    private final DistortedScreen mScreen;
+    private final float mObjWidth, mObjHeight, mObjDepth;
+    private final Static3D mScale;
+    private final Static1D mAlpha;
 
     Static4D mQuat1, mQuat2;
     int mScreenMin;
@@ -62,6 +69,7 @@ class InflateRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
     InflateRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
 
       mAlpha = new Static1D(1.0f);
       mScale= new Static3D(1,1,1);
@@ -154,7 +162,7 @@ class InflateRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
       VertexEffectScale.enable();
       FragmentEffectAlpha.enable();
 
-      DistortedLibrary.onSurfaceCreated(act,this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -163,4 +171,32 @@ class InflateRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
       {
       android.util.Log.e("Inflate", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Inflate", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
index 134c7c6..70dff94 100644
--- a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
+++ b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
@@ -40,6 +40,10 @@ import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 import org.distorted.library.message.EffectListener;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -47,17 +51,19 @@ import android.opengl.GLSurfaceView;
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // Show how to use the notifyWhenFinished / effectFinished APIs
 
-class ListenerRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.ExceptionListener
+class ListenerRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.LibraryUser
 {
    private final int NUM_CONCURRENT_BUBBLES = 12;
 
-   private GLSurfaceView mView;
-   private DistortedEffects mEffects;
-   private DistortedScreen mScreen;
-   private DistortedTexture mTexture;
+   private final GLSurfaceView mView;
+   private final Resources mResources;
+   private final DistortedEffects mEffects;
+   private final DistortedScreen mScreen;
+   private final DistortedTexture mTexture;
+   private final Random mRnd;
+   private final Static3D mScale;
+
    private MeshSquare mMesh;
-   private Random mRnd;
-   private Static3D mScale;
    private float mBmpRatio;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -65,6 +71,7 @@ class ListenerRenderer implements GLSurfaceView.Renderer, EffectListener, Distor
    ListenerRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
 
       mTexture = new DistortedTexture();
       mScreen  = new DistortedScreen();
@@ -174,7 +181,7 @@ class ListenerRenderer implements GLSurfaceView.Renderer, EffectListener, Distor
 
      VertexEffectDistort.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -183,4 +190,32 @@ class ListenerRenderer implements GLSurfaceView.Renderer, EffectListener, Distor
      {
      android.util.Log.e("Listener", ex.getMessage() );
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Listener", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java b/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java
index 76d4807..ec0c46b 100644
--- a/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java
+++ b/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java
@@ -19,7 +19,9 @@
 
 package org.distorted.examples.meshfile;
 
+import android.app.ActivityManager;
 import android.content.Context;
+import android.content.pm.ConfigurationInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -65,19 +67,21 @@ import static org.distorted.objectlib.main.TwistyObject.MODE_NORM;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private static final float SQ3 = (float)Math.sqrt(3);
     private final float DEFAULT_SCALE = 0.3f;
 
     private final GLSurfaceView mView;
-    private DistortedTexture mTexture;
+    private final Resources mResources;
     private final DistortedScreen mScreen;
     private final DistortedEffects mEffects;
     private final Static3D mScale;
+
+    private DistortedTexture mTexture;
+    private MeshBase mMesh;
     private long mTime;
     private float mCurrentScale;
-    private MeshBase mMesh;
 
     Static4D mQuat1, mQuat2;
     int mScreenMin;
@@ -87,6 +91,8 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
     MeshFileRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
+
       mScreen = new DistortedScreen();
       mScale= new Static3D(1,1,1);
       Static3D center=new Static3D(0,0,0);
@@ -142,14 +148,7 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
       Effect.enableEffects(EffectType.VERTEX);
       DistortedLibrary.setMax(EffectType.VERTEX, 20);
       DistortedLibrary.needTransformFeedback();
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void distortedException(Exception ex)
-      {
-      android.util.Log.e("MeshFile", ex.getMessage() );
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -405,4 +404,39 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
       {
       return mMesh.getNumTexComponents();
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void distortedException(Exception ex)
+      {
+      android.util.Log.e("MeshFile", ex.getMessage() );
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("MeshFile", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/meshjoin/MeshJoinRenderer.java b/src/main/java/org/distorted/examples/meshjoin/MeshJoinRenderer.java
index ea15749..e63c801 100644
--- a/src/main/java/org/distorted/examples/meshjoin/MeshJoinRenderer.java
+++ b/src/main/java/org/distorted/examples/meshjoin/MeshJoinRenderer.java
@@ -19,12 +19,15 @@
 
 package org.distorted.examples.meshjoin;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.opengl.GLSurfaceView;
 
-import org.distorted.library.effect.EffectType;
 import org.distorted.library.effect.MatrixEffectQuaternion;
 import org.distorted.library.effect.MatrixEffectScale;
 import org.distorted.library.effect.VertexEffectDeform;
@@ -45,21 +48,25 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import java.io.InputStream;
+
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class MeshJoinRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class MeshJoinRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
-    private GLSurfaceView mView;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedScreen mScreen;
+    private final DistortedEffects mEffects;
+    private final Static3D mScale;
+    private final VertexEffectSink mSink;
+
     private DistortedTexture mTexture;
-    private DistortedScreen mScreen;
-    private DistortedEffects mEffects;
-    private Static3D mScale;
     private MeshBase mMesh;
     private int mSinkAssociation;
-    private VertexEffectSink mSink;
 
     Static4D mQuat1, mQuat2;
     int mScreenMin;
@@ -69,6 +76,8 @@ class MeshJoinRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
     MeshJoinRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
+
       mScreen = new DistortedScreen();
       mScale= new Static3D(1,1,1);
       Static3D center=new Static3D(0,0,0);
@@ -131,14 +140,7 @@ class MeshJoinRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
 
       VertexEffectSink.enable();
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void distortedException(Exception ex)
-      {
-      android.util.Log.e("MeshJoin", ex.getMessage() );
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -249,9 +251,9 @@ class MeshJoinRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
       Static1D angle  = new Static1D(angleFaces);
       Static3D axis1  = new Static3D(  -1, 0,      0);
       Static3D axis2  = new Static3D(0.5f, 0, -SQ3/2);
-      Static3D axis3  = new Static3D(0.5f, 0, +SQ3/2);
+      Static3D axis3  = new Static3D(0.5f, 0,  SQ3/2);
       Static3D center1= new Static3D(0,-SQ3*SQ2/12,-SQ3/6);
-      Static3D center2= new Static3D(0,-SQ3*SQ2/12,+SQ3/3);
+      Static3D center2= new Static3D(0,-SQ3*SQ2/12, SQ3/3);
 
       VertexEffectScale   effect1 = new VertexEffectScale ( new Static3D(1,SQ3/2,1) );
       VertexEffectRotate  effect2 = new VertexEffectRotate( new Static1D(90), new Static3D(1,0,0), new Static3D(0,0,0) );
@@ -285,4 +287,39 @@ class MeshJoinRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
 
       return result;
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void distortedException(Exception ex)
+      {
+      android.util.Log.e("MeshJoin", ex.getMessage() );
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("MeshJoin", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/mirror/MirrorRenderer.java b/src/main/java/org/distorted/examples/mirror/MirrorRenderer.java
index 9fb7cbc..912f226 100644
--- a/src/main/java/org/distorted/examples/mirror/MirrorRenderer.java
+++ b/src/main/java/org/distorted/examples/mirror/MirrorRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.mirror;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -45,7 +49,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class MirrorRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class MirrorRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
    private static final float MIRROR_SCALE     =0.70f;  // each next mirror will be 70% of the size or the previous
    private static final float HEAD_SCALE       =0.30f;  // Head's height will be 30% of the height of the mirror
@@ -56,6 +60,7 @@ class MirrorRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excepti
    private static final float MIRROR_MOVE_V    =0.22f;  // Move the mirror up
 
    private final GLSurfaceView mView;
+   private final Resources mResources;
    private final DistortedEffects mEffectsMirror, mEffectsHead, mEffectsScreen;
    private final DistortedEffects mEffectsOffscreen1, mEffectsOffscreen2;
    private final DistortedScreen mScreen;
@@ -74,8 +79,9 @@ class MirrorRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excepti
 
    MirrorRenderer(GLSurfaceView view)
       { 
-      mView    = view;
-      mScreen  = new DistortedScreen();
+      mView     = view;
+      mResources= view.getResources();
+      mScreen   = new DistortedScreen();
 
       mQuad1     = new MeshQuad();
       mQuad2     = new MeshQuad();
@@ -220,7 +226,7 @@ class MirrorRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excepti
       VertexEffectScale.enable();
       FragmentEffectBrightness.enable();
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -229,4 +235,32 @@ class MirrorRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excepti
       {
       android.util.Log.e("Mirror", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Mirror", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
index ae7d17f..b6e9ce4 100644
--- a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
+++ b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
@@ -37,20 +37,26 @@ import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class MonaLisaRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class MonaLisaRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
-    private GLSurfaceView mView;
-    private DistortedEffects mEffects;
-    private DistortedTexture mTexture;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedEffects mEffects;
+    private final DistortedTexture mTexture;
+    private final DistortedScreen mScreen;
+    private final Static3D mScale;
+
     private MeshSquare mMesh;
-    private DistortedScreen mScreen;
-    private Static3D mScale;
     private float mBmpRatio;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -58,6 +64,7 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
     MonaLisaRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
 
       // Centers of the Effects.
       // center = (0,0,0) would be the midpoint of the Bitmap.
@@ -137,7 +144,7 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
           {
           is.close();
           } 
-        catch(IOException e) { }
+        catch(IOException ignored) { }
         }  
 
       mBmpRatio = (float)bitmap.getHeight()/bitmap.getWidth();
@@ -161,7 +168,7 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
       // before the call to DistortedLibrary.onCreate(). Best done here.
       VertexEffectDistort.enable();
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -170,4 +177,32 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
       {
       android.util.Log.e("MonaLisa", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("MonaLisa", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java b/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
index 0daf2a5..c168b9b 100644
--- a/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
+++ b/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
@@ -22,6 +22,10 @@ package org.distorted.examples.movingeffects;
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -44,33 +48,38 @@ import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.mesh.MeshSquare;
 import org.distorted.library.type.Static3D;
 
+import java.io.InputStream;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class MovingEffectsRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class MovingEffectsRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
    {  
-   private MovingEffectsSurfaceView mView;
+   private final MovingEffectsSurfaceView mView;
+   private final DistortedEffects mEffects;
+   private final DistortedTexture mTexture;
+   private final DistortedScreen mScreen;
+   private final Static3D mScaleMatrix, mScaleVertex;
+   private final Paint mPaint;
+   private final Resources mResources;
+
+   private MeshSquare mMesh;
    private Canvas mCanvas;
    private Bitmap mBitmap;
-   private Paint mPaint;
    private int texW, texH;
-
-   private DistortedEffects mEffects;
-   private DistortedTexture mTexture;
-   private DistortedScreen mScreen;
-   private MeshSquare mMesh;
    private boolean mRefresh;
-   private Static3D mScaleMatrix, mScaleVertex;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    MovingEffectsRenderer(MovingEffectsSurfaceView v)
-     {    
+     {
+     mView = v;
+     mResources = v.getResources();
+
      mPaint = new Paint();
      mPaint.setAntiAlias(true);
      mPaint.setFakeBoldText(true);
      mPaint.setStyle(Style.FILL);
 
-     mView   = v;
      mEffects= new DistortedEffects();
      mScreen = new DistortedScreen();
      mTexture= new DistortedTexture();
@@ -178,7 +187,7 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer, DistortedLibrary.
      FragmentEffectChroma.enable();
      FragmentEffectAlpha.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -187,4 +196,32 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer, DistortedLibrary.
      {
      android.util.Log.e("MovingEffects", ex.getMessage() );
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+      {
+      android.util.Log.e("MovingEffects", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java b/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java
index b864aed..ed4c256 100644
--- a/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java
+++ b/src/main/java/org/distorted/examples/movingglow/MovingGlowRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.movingglow;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -52,28 +56,31 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class MovingGlowRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.ExceptionListener
+class MovingGlowRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.LibraryUser
 {
    private static final int[] colors  = new int[] {0,0,1,  1,0,1,  1,0,0,  1,1,0,  0,1,0,  1,1,1}; // blue, pink, red, yellow, green, white
    private static final int FLASH_TIME = 2000;
    private static final int LEAF_SIZE = 100;
    private static final int NUM_LEAVES= colors.length/3;
    
-   private GLSurfaceView mView;
-   private DistortedTexture mLeaf;
-   private DistortedScreen mScreen;
-   private DistortedEffects[] mLeafEffects = new DistortedEffects[NUM_LEAVES];
-   private PostprocessEffectGlow[] mGlow = new PostprocessEffectGlow[NUM_LEAVES];
+   private final GLSurfaceView mView;
+   private final Resources mResources;
+   private final DistortedTexture mLeaf;
+   private final DistortedScreen mScreen;
+   private final DistortedEffects[] mLeafEffects = new DistortedEffects[NUM_LEAVES];
+   private final PostprocessEffectGlow[] mGlow = new PostprocessEffectGlow[NUM_LEAVES];
+   private final Static3D mScale;
+   private final Dynamic2D mHaloAndRadiusDyn;
+   private final Dynamic4D[] mColorDyn;
+
    private int mGlowing;
-   private Static3D mScale;
-   private Dynamic2D mHaloAndRadiusDyn;
-   private Dynamic4D[] mColorDyn;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    MovingGlowRenderer(GLSurfaceView v)
       {     
       mView = v;
+      mResources = v.getResources();
 
       MeshQuad mesh = new MeshQuad();
       mesh.setComponentCenter(0,0,0,-0.1f);
@@ -194,7 +201,7 @@ class MovingGlowRenderer implements GLSurfaceView.Renderer, EffectListener, Dist
          {
          is.close();
          }
-       catch(IOException e) { }
+       catch(IOException ignored) { }
        }
       
      mLeaf.setTexture(leaf);
@@ -202,7 +209,7 @@ class MovingGlowRenderer implements GLSurfaceView.Renderer, EffectListener, Dist
      FragmentEffectChroma.enable();
      PostprocessEffectGlow.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -211,4 +218,32 @@ class MovingGlowRenderer implements GLSurfaceView.Renderer, EffectListener, Dist
       {
       android.util.Log.e("MovingGlow", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("MovingGlow", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/multiblur/MultiblurRenderer.java b/src/main/java/org/distorted/examples/multiblur/MultiblurRenderer.java
index 6c7bc2e..3b8d4ae 100644
--- a/src/main/java/org/distorted/examples/multiblur/MultiblurRenderer.java
+++ b/src/main/java/org/distorted/examples/multiblur/MultiblurRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.multiblur;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -47,7 +51,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class MultiblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class MultiblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private static final int[] MOVE_VEC =
         {
@@ -63,16 +67,18 @@ class MultiblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
 
     private static final int NUM_OBJECTS = MOVE_VEC.length/3;
 
-    private GLSurfaceView mView;
-    private DistortedTexture mTex1, mTex2;
-    private DistortedNode[] mNode;
-    private Static3D[]  mMoveVector;
-    private Static2D mBlurHaloRadius;
-    private DistortedScreen mScreen;
-    private PostprocessEffectBlur mBlur;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedTexture mTex1, mTex2;
+    private final DistortedNode[] mNode;
+    private final Static3D[]  mMoveVector;
+    private final Static2D mBlurHaloRadius;
+    private final DistortedScreen mScreen;
+    private final PostprocessEffectBlur mBlur;
+    private final boolean[] mBlurStatus;
+    private final Static3D mScale;
+
     private int mDistance;
-    private boolean[] mBlurStatus;
-    private Static3D mScale;
 
     Static4D mQuat1, mQuat2;
     int mScreenMin;
@@ -82,6 +88,7 @@ class MultiblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
     MultiblurRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
       mDistance = -1;
 
       mBlurStatus = new boolean[NUM_OBJECTS];
@@ -188,7 +195,7 @@ class MultiblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
           is1.close();
           is2.close();
           }
-        catch(IOException e) { }
+        catch(IOException ignored) { }
         }  
 
       mTex1.setTexture(bitmap1);
@@ -196,14 +203,7 @@ class MultiblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
 
       PostprocessEffectBlur.enable();
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void distortedException(Exception ex)
-      {
-      android.util.Log.e("Multiblur", ex.getMessage() );
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -262,4 +262,39 @@ class MultiblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
         android.util.Log.e("renderer", "Error, number: "+number+" checked: "+checked );
         }
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void distortedException(Exception ex)
+      {
+      android.util.Log.e("Multiblur", ex.getMessage() );
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Multiblur", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java b/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java
index a6bb957..b1e680a 100644
--- a/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java
+++ b/src/main/java/org/distorted/examples/objecttree/ObjectTreeRenderer.java
@@ -46,6 +46,9 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -54,12 +57,13 @@ import android.opengl.GLSurfaceView;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class ObjectTreeRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class ObjectTreeRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
    private static final int NODE_FBO_SIZE = 300;
    private static final int GRID = 10;
 
    private final GLSurfaceView mView;
+   private final Resources mResources;
    private final DistortedEffects mEffectsNode,mEffectsGrid;
    private final DistortedScreen mScreen;
    private final Static3D mScale;
@@ -75,7 +79,9 @@ class ObjectTreeRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
 
    ObjectTreeRenderer(GLSurfaceView v)
       {
-      mView   = v;
+      mView = v;
+      mResources = v.getResources();
+
       mDepth  = true;
       mScale  = new Static3D(1,1,1);
       Dynamic1D chromaDyn = new Dynamic1D(5000,0.0f);
@@ -202,7 +208,7 @@ class ObjectTreeRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
       VertexEffectSink.enable();
       FragmentEffectChroma.enable();
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -211,4 +217,32 @@ class ObjectTreeRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
       {
       android.util.Log.e("ObjectTree", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("ObjectTree", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java b/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
index f2aecff..945e85e 100644
--- a/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
+++ b/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
@@ -41,28 +41,33 @@ import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static1D;
 import org.distorted.library.main.DistortedTexture;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class OlimpicRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class OlimpicRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
    private static final int LEAF_SIZE = 100;
    private static final int NUM_CIRCLES = 5;
    static final int NUM_LEAVES  = 8;
    
-   private GLSurfaceView mView;
-   private DistortedNode mRoot;
-   private DistortedTexture mLeaf;
-   private DistortedScreen mScreen;
-   private MeshQuad mLeafMesh;
-   private int mPrevRendered, mCurrRendered;
-   private Static3D mScale;
+   private final GLSurfaceView mView;
+   private final DistortedNode mRoot;
+   private final DistortedTexture mLeaf;
+   private final DistortedScreen mScreen;
+   private final MeshQuad mLeafMesh;
+   private final Static3D mScale;
+   private final DistortedNode[] mCircleNode = new DistortedNode[NUM_CIRCLES];
+   private final DistortedEffects[] mEffects = new DistortedEffects[NUM_LEAVES];
+   private final Resources mResources;
 
-   private DistortedNode[] mCircleNode = new DistortedNode[NUM_CIRCLES];
-   private DistortedEffects[] mEffects = new DistortedEffects[NUM_LEAVES];
+   private int mPrevRendered, mCurrRendered;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -88,6 +93,7 @@ class OlimpicRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
    OlimpicRenderer(GLSurfaceView v)
       {     
       mView = v;
+      mResources = v.getResources();
 
       mPrevRendered = -1;
       mCurrRendered = -1;
@@ -177,7 +183,7 @@ class OlimpicRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
      {
      float horiRatio = (float)width ;
      float vertRatio = (float)height;
-     float factor    = horiRatio > vertRatio ? vertRatio : horiRatio;
+     float factor    = Math.min(horiRatio,vertRatio);
 
      mScale.set(factor,factor,factor);
      mScreen.resize(width, height);
@@ -200,14 +206,14 @@ class OlimpicRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
          {
          is.close();
          }
-       catch(IOException e) { }
+       catch(IOException ignored) { }
        }
       
      mLeaf.setTexture(leaf);
 
      FragmentEffectChroma.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -216,4 +222,32 @@ class OlimpicRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
      {
      android.util.Log.e("Olympic", ex.getMessage() );
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+     {
+     Context context = mView.getContext();
+     final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+     final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+     int glESversion = configurationInfo.reqGlEsVersion;
+     int major = glESversion >> 16;
+     int minor = glESversion & 0xff;
+
+     return 100*major + 10*minor;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+     {
+     return mResources.openRawResource(fileID);
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+     {
+     android.util.Log.e("Olympic", message );
+     }
 }
diff --git a/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java b/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java
index 66f6bed..5bafdc0 100644
--- a/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java
+++ b/src/main/java/org/distorted/examples/postprocesstree/PostprocessTreeRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.postprocesstree;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -49,22 +53,24 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class PostprocessTreeRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class PostprocessTreeRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
    private static final int LEAF_SIZE = 100;
    private static final int NUM_LEAVES  = 8;
    
-   private GLSurfaceView mView;
-   private DistortedTexture mLeaf;
-   private DistortedScreen mScreen;
-   private Static3D mScale;
-   private Static2D mHaloRadius;
+   private final GLSurfaceView mView;
+   private final Resources mResources;
+   private final DistortedTexture mLeaf;
+   private final DistortedScreen mScreen;
+   private final Static3D mScale;
+   private final Static2D mHaloRadius;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    PostprocessTreeRenderer(GLSurfaceView v)
       {     
       mView = v;
+      mResources = v.getResources();
 
       final int OUTER = 9;
       final int INNER = 4;
@@ -177,7 +183,7 @@ class PostprocessTreeRenderer implements GLSurfaceView.Renderer, DistortedLibrar
          {
          is.close();
          }
-       catch(IOException e) { }
+       catch(IOException ignored) { }
        }
       
      mLeaf.setTexture(leaf);
@@ -185,7 +191,7 @@ class PostprocessTreeRenderer implements GLSurfaceView.Renderer, DistortedLibrar
      FragmentEffectChroma.enable();
      PostprocessEffectBlur.enable();
 
-     DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -194,4 +200,32 @@ class PostprocessTreeRenderer implements GLSurfaceView.Renderer, DistortedLibrar
      {
      android.util.Log.e("PostprocessTree", ex.getMessage() );
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void logMessage(String message)
+      {
+      android.util.Log.e("PostprocessTree", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/predeform/PredeformRenderer.java b/src/main/java/org/distorted/examples/predeform/PredeformRenderer.java
index 5ee1469..dbcb290 100644
--- a/src/main/java/org/distorted/examples/predeform/PredeformRenderer.java
+++ b/src/main/java/org/distorted/examples/predeform/PredeformRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.predeform;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.opengl.GLSurfaceView;
 
 import org.distorted.library.effect.EffectType;
@@ -36,6 +40,7 @@ import org.distorted.library.type.DynamicQuat;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import java.io.InputStream;
 import java.util.ArrayList;
 
 import javax.microedition.khronos.egl.EGLConfig;
@@ -43,12 +48,13 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class PredeformRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class PredeformRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private static final float FOV = 30.0f;
     private static final float NEAR = 0.1f;
 
     private final GLSurfaceView mView;
+    private final Resources mResources;
     private final DistortedTexture mTexture;
     private final DistortedEffects mEffects1, mEffects2;
     private final MeshBase mMesh1, mMesh2;
@@ -63,6 +69,7 @@ class PredeformRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
     PredeformRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
 
       mScale= new Static3D(1,1,1);
       mMove1= new Static3D(0,0,0);
@@ -133,14 +140,14 @@ class PredeformRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
         {
         float factor = SCALE*(Math.min(width, 0.5f*height));
         mScale.set(factor,factor,factor);
-        mMove1.set(0,+height*0.25f,0);
+        mMove1.set(0, height*0.25f,0);
         mMove2.set(0,-height*0.25f,0);
         }
       else
         {
         float factor = SCALE*(Math.min( 0.5f*width, height));
         mScale.set(factor,factor,factor);
-        mMove1.set(+width*0.25f,0,0);
+        mMove1.set( width*0.25f,0,0);
         mMove2.set(-width*0.25f,0,0);
         }
 
@@ -181,7 +188,7 @@ class PredeformRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
       Effect.enableEffects(EffectType.VERTEX);
 
       DistortedLibrary.needTransformFeedback();
-      DistortedLibrary.onSurfaceCreated(act, this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -190,4 +197,32 @@ class PredeformRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exce
       {
       android.util.Log.e("Predeform", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Predeform", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java b/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
index 5e5bb90..5c9c05f 100644
--- a/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
+++ b/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
@@ -33,29 +33,39 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Paint.Style;
 import android.opengl.GLSurfaceView;
 
+import java.io.InputStream;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class ProjectionRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class ProjectionRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
-   private GLSurfaceView mView;
-   private DistortedEffects mEffects;
-   private DistortedScreen mScreen;
+   private final GLSurfaceView mView;
+   private final Resources mResources;
+   private final DistortedEffects mEffects;
+   private final DistortedScreen mScreen;
+   private final DistortedTexture mTexture;
+   private final Static3D mScale;
+
    private MeshSquare mMesh;
-   private DistortedTexture mTexture;
    private float mF, mNear;
-   private Static3D mScale;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    ProjectionRenderer(GLSurfaceView view)
       { 
-      mView   = view;
+      mView = view;
+      mResources = view.getResources();
+
       mEffects= new DistortedEffects();
       mScreen = new DistortedScreen();
 
@@ -145,8 +155,7 @@ class ProjectionRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
       {
       VertexEffectDeform.enable();
-
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -155,4 +164,32 @@ class ProjectionRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
       {
       android.util.Log.e("Projection", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Projection", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java b/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
index 7bb47f6..acc3ba4 100644
--- a/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
+++ b/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
@@ -40,26 +40,33 @@ import org.distorted.library.type.DynamicQuat;
 import org.distorted.library.type.Static4D;
 import org.distorted.library.type.Static3D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class QuaternionRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class QuaternionRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
   {
   private static final int NUM_QUATERNIONS = 5;
 
-  private GLSurfaceView mView;
-  private DistortedTexture mTexture;
-  private DistortedScreen mScreen;
-  private Static3D mScale;
+  private final GLSurfaceView mView;
+  private final Resources mResources;
+  private final DistortedTexture mTexture;
+  private final DistortedScreen mScreen;
+  private final Static3D mScale;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   QuaternionRenderer(GLSurfaceView v)
     {
-    mView    = v;
+    mView = v;
+    mResources = v.getResources();
+
     mTexture = new DistortedTexture();
 
     DistortedEffects effects = new DistortedEffects();
@@ -127,12 +134,12 @@ class QuaternionRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
         {
         is.close();
         } 
-      catch(IOException e) { }
+      catch(IOException ignored) { }
       }  
       
     mTexture.setTexture(bitmap);
 
-    DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+    DistortedLibrary.onSurfaceCreated(this);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -141,4 +148,32 @@ class QuaternionRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
     {
     android.util.Log.e("Quaternion", ex.getMessage() );
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int openGlVersion()
+    {
+    Context context = mView.getContext();
+    final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+    final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+    int glESversion = configurationInfo.reqGlEsVersion;
+    int major = glESversion >> 16;
+    int minor = glESversion & 0xff;
+
+    return 100*major + 10*minor;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public InputStream localFile(int fileID)
+    {
+    return mResources.openRawResource(fileID);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void logMessage(String message)
+    {
+    android.util.Log.e("Quaternion", message );
+    }
   }
diff --git a/src/main/java/org/distorted/examples/rubik/RubikRenderer.java b/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
index c316af3..a582297 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.rubik;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.opengl.GLSurfaceView;
 
 import org.distorted.library.effect.VertexEffectSink;
@@ -27,26 +31,29 @@ import org.distorted.library.main.DistortedScreen;
 import org.distorted.library.message.EffectListener;
 import org.distorted.library.type.Static3D;
 
+import java.io.InputStream;
+
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class RubikRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.ExceptionListener
+class RubikRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.LibraryUser
 {
     private static final float CUBE_SCREEN_RATIO = 0.5f;
     private static final float CAMERA_DISTANCE   = 0.6f;  // 0.6 of the length of max(scrHeight,scrWidth)
     private static final int MIN_CUBE_SIZE = 1;
     private static final int MAX_CUBE_SIZE = 6;
 
-    private RubikSurfaceView mView;
-    private DistortedScreen mScreen;
-    private Static3D mScale;
+    private final RubikSurfaceView mView;
+    private final DistortedScreen mScreen;
+    private final Static3D mScale;
+    private final Resources mResources;
+
+    private RubikCube mCube;
     private int mNextCubeSize;
     private boolean mChangeCubeSizeNow;
     private int mNumCube;
-    private RubikCube mCube;
-
     private int mScreenWidth, mScreenHeight;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -54,7 +61,7 @@ class RubikRenderer implements GLSurfaceView.Renderer, EffectListener, Distorted
     RubikRenderer(RubikSurfaceView v)
       {
       mView = v;
-
+      mResources = v.getResources();
       mScreen = new DistortedScreen();
 
       mScreenWidth = mScreenHeight = 0;
@@ -94,7 +101,7 @@ class RubikRenderer implements GLSurfaceView.Renderer, EffectListener, Distorted
     
    public void onSurfaceChanged(GL10 glUnused, int width, int height)
      {
-     float cameraDistance = CAMERA_DISTANCE*(width>height ? width:height);
+     float cameraDistance = CAMERA_DISTANCE*(Math.max(width,height));
      float fovInDegrees   = computeFOV(cameraDistance,height);
 
      mScreen.setProjection( fovInDegrees, 0.1f);
@@ -112,14 +119,7 @@ class RubikRenderer implements GLSurfaceView.Renderer, EffectListener, Distorted
      {
      createNextCube();
      VertexEffectSink.enable();
-     DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
-     }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   public void distortedException(Exception ex)
-     {
-     android.util.Log.e("Rubik", ex.getMessage() );
+     DistortedLibrary.onSurfaceCreated(this);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -154,4 +154,39 @@ class RubikRenderer implements GLSurfaceView.Renderer, EffectListener, Distorted
      float scaleFactor = CUBE_SCREEN_RATIO * Math.min(screenWidth,screenHeight) / mCube.getSize();
      mScale.set(scaleFactor,scaleFactor,scaleFactor);
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void distortedException(Exception ex)
+     {
+     android.util.Log.e("Rubik", ex.getMessage() );
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int openGlVersion()
+     {
+     Context context = mView.getContext();
+     final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+     final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+     int glESversion = configurationInfo.reqGlEsVersion;
+     int major = glESversion >> 16;
+     int minor = glESversion & 0xff;
+
+     return 100*major + 10*minor;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public InputStream localFile(int fileID)
+     {
+     return mResources.openRawResource(fileID);
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void logMessage(String message)
+     {
+     android.util.Log.e("Rubik", message );
+     }
 }
diff --git a/src/main/java/org/distorted/examples/save/SaveRenderer.java b/src/main/java/org/distorted/examples/save/SaveRenderer.java
index a4eb059..c7fa648 100644
--- a/src/main/java/org/distorted/examples/save/SaveRenderer.java
+++ b/src/main/java/org/distorted/examples/save/SaveRenderer.java
@@ -44,6 +44,10 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLES31;
@@ -52,17 +56,18 @@ import android.os.Environment;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class SaveRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class SaveRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
   {
-  private GLSurfaceView mView;
-  private DistortedEffects mEffects;
+  private final GLSurfaceView mView;
+  private final DistortedEffects mEffects;
+  private final DistortedScreen mScreen;
+  private final Static1D s0;
+  private final Static3D mScaleFactor, mScaleMain, mScaleVertex;
+  private final Resources mResources;
+
   private DistortedFramebuffer mOffscreen;
   private DistortedTexture mTexture;
   private MeshSquare mMesh;
-  private DistortedScreen mScreen;
-  private Static1D s0;
-  private Static3D mScaleFactor, mScaleMain, mScaleVertex;
-
   private float mScale;
   private int bmpHeight, bmpWidth;
   private int scrHeight, scrWidth;
@@ -75,7 +80,8 @@ class SaveRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
   SaveRenderer(GLSurfaceView v)
     {
     mView = v;
-      
+    mResources = v.getResources();
+
     boobsSink  = 1.0f;
 
     Static3D pLeft = new Static3D(-68, 36, 0);
@@ -249,7 +255,7 @@ class SaveRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
     VertexEffectScale.enable();
     VertexEffectSink.enable();
 
-    DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+    DistortedLibrary.onSurfaceCreated(this);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -258,4 +264,32 @@ class SaveRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
     {
     android.util.Log.e("Save", ex.getMessage() );
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int openGlVersion()
+     {
+     Context context = mView.getContext();
+     final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+     final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+     int glESversion = configurationInfo.reqGlEsVersion;
+     int major = glESversion >> 16;
+     int minor = glESversion & 0xff;
+
+     return 100*major + 10*minor;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public InputStream localFile(int fileID)
+     {
+     return mResources.openRawResource(fileID);
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void logMessage(String message)
+     {
+     android.util.Log.e("Save", message );
+     }
   }
diff --git a/src/main/java/org/distorted/examples/singlemesh/SingleMeshRenderer.java b/src/main/java/org/distorted/examples/singlemesh/SingleMeshRenderer.java
index 2a5fe0d..82f2ff7 100644
--- a/src/main/java/org/distorted/examples/singlemesh/SingleMeshRenderer.java
+++ b/src/main/java/org/distorted/examples/singlemesh/SingleMeshRenderer.java
@@ -19,12 +19,15 @@
 
 package org.distorted.examples.singlemesh;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.opengl.GLSurfaceView;
 
-import org.distorted.library.effect.EffectType;
 import org.distorted.library.effect.MatrixEffectMove;
 import org.distorted.library.effect.MatrixEffectQuaternion;
 import org.distorted.library.effect.MatrixEffectScale;
@@ -45,16 +48,18 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import java.io.InputStream;
+
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class SingleMeshRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class SingleMeshRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private static final float DIST = 0.5f;
 
-    private static Static3D[] AXIS = new Static3D[]
+    private static final Static3D[] AXIS = new Static3D[]
          {
            new Static3D(1,0,0),
            new Static3D(0,1,0),
@@ -102,16 +107,18 @@ class SingleMeshRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
            new Static3D(+DIST,+DIST,+DIST),
          };
 
-    private GLSurfaceView mView;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedScreen mScreen;
+    private final DistortedEffects mEffects;
+    private final Static3D mScale;
+    private final VertexEffectRotate mRotate;
+    private final Dynamic1D mAngleDyn;
+    private final Static1D mAngle;
+    private final Static3D mAxis;
+
     private DistortedTexture mTexture;
-    private DistortedScreen mScreen;
-    private DistortedEffects mEffects;
-    private Static3D mScale;
     private MeshBase mMesh;
-    private VertexEffectRotate mRotate;
-    private Dynamic1D mAngleDyn;
-    private Static1D mAngle;
-    private Static3D mAxis;
 
     Static4D mQuat1, mQuat2;
     int mScreenMin;
@@ -121,6 +128,8 @@ class SingleMeshRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
     SingleMeshRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
+
       mScreen = new DistortedScreen();
       mScale= new Static3D(1,1,1);
       Static3D center=new Static3D(0,0,0);
@@ -184,14 +193,7 @@ class SingleMeshRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
 
       VertexEffectRotate.enable();
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void distortedException(Exception ex)
-      {
-      android.util.Log.e("SingleMesh", ex.getMessage() );
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -270,22 +272,22 @@ class SingleMeshRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
       float d2 =-0.05f;
       float d3 = 0.12f;
 
-      Static3D dCen0 = new Static3D( d1*(+0.5f), d1*(+0.5f), d1*(+0.5f) );
-      Static3D dCen1 = new Static3D( d1*(+0.5f), d1*(+0.5f), d1*(-0.5f) );
-      Static3D dCen2 = new Static3D( d1*(+0.5f), d1*(-0.5f), d1*(+0.5f) );
-      Static3D dCen3 = new Static3D( d1*(+0.5f), d1*(-0.5f), d1*(-0.5f) );
-      Static3D dCen4 = new Static3D( d1*(-0.5f), d1*(+0.5f), d1*(+0.5f) );
-      Static3D dCen5 = new Static3D( d1*(-0.5f), d1*(+0.5f), d1*(-0.5f) );
-      Static3D dCen6 = new Static3D( d1*(-0.5f), d1*(-0.5f), d1*(+0.5f) );
+      Static3D dCen0 = new Static3D( d1*( 0.5f), d1*( 0.5f), d1*( 0.5f) );
+      Static3D dCen1 = new Static3D( d1*( 0.5f), d1*( 0.5f), d1*(-0.5f) );
+      Static3D dCen2 = new Static3D( d1*( 0.5f), d1*(-0.5f), d1*( 0.5f) );
+      Static3D dCen3 = new Static3D( d1*( 0.5f), d1*(-0.5f), d1*(-0.5f) );
+      Static3D dCen4 = new Static3D( d1*(-0.5f), d1*( 0.5f), d1*( 0.5f) );
+      Static3D dCen5 = new Static3D( d1*(-0.5f), d1*( 0.5f), d1*(-0.5f) );
+      Static3D dCen6 = new Static3D( d1*(-0.5f), d1*(-0.5f), d1*( 0.5f) );
       Static3D dCen7 = new Static3D( d1*(-0.5f), d1*(-0.5f), d1*(-0.5f) );
 
-      Static3D dVec0 = new Static3D( d2*(+0.5f), d2*(+0.5f), d2*(+0.5f) );
-      Static3D dVec1 = new Static3D( d2*(+0.5f), d2*(+0.5f), d2*(-0.5f) );
-      Static3D dVec2 = new Static3D( d2*(+0.5f), d2*(-0.5f), d2*(+0.5f) );
-      Static3D dVec3 = new Static3D( d2*(+0.5f), d2*(-0.5f), d2*(-0.5f) );
-      Static3D dVec4 = new Static3D( d2*(-0.5f), d2*(+0.5f), d2*(+0.5f) );
-      Static3D dVec5 = new Static3D( d2*(-0.5f), d2*(+0.5f), d2*(-0.5f) );
-      Static3D dVec6 = new Static3D( d2*(-0.5f), d2*(-0.5f), d2*(+0.5f) );
+      Static3D dVec0 = new Static3D( d2*( 0.5f), d2*( 0.5f), d2*( 0.5f) );
+      Static3D dVec1 = new Static3D( d2*( 0.5f), d2*( 0.5f), d2*(-0.5f) );
+      Static3D dVec2 = new Static3D( d2*( 0.5f), d2*(-0.5f), d2*( 0.5f) );
+      Static3D dVec3 = new Static3D( d2*( 0.5f), d2*(-0.5f), d2*(-0.5f) );
+      Static3D dVec4 = new Static3D( d2*(-0.5f), d2*( 0.5f), d2*( 0.5f) );
+      Static3D dVec5 = new Static3D( d2*(-0.5f), d2*( 0.5f), d2*(-0.5f) );
+      Static3D dVec6 = new Static3D( d2*(-0.5f), d2*(-0.5f), d2*( 0.5f) );
       Static3D dVec7 = new Static3D( d2*(-0.5f), d2*(-0.5f), d2*(-0.5f) );
 
       Static4D dReg  = new Static4D(0,0,0,d3);
@@ -369,4 +371,39 @@ class SingleMeshRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exc
 
       return result;
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void distortedException(Exception ex)
+      {
+      android.util.Log.e("SingleMesh", ex.getMessage() );
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("SingleMesh", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/sink/SinkRenderer.java b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
index 33ee1bb..9f05ab9 100644
--- a/src/main/java/org/distorted/examples/sink/SinkRenderer.java
+++ b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
@@ -38,15 +38,20 @@ import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class SinkRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class SinkRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
   {
   private final GLSurfaceView mView;
+  private final Resources mResources;
   private final DistortedEffects mEffects;
   private final DistortedScreen mScreen;
   private final DistortedTexture mTexture;
@@ -60,7 +65,9 @@ class SinkRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
 
   SinkRenderer(GLSurfaceView v)
     { 
-    mView    = v;
+    mView = v;
+    mResources = v.getResources();
+
     mTexture = new DistortedTexture();
     mEffects = new DistortedEffects();
     mScreen  = new DistortedScreen();
@@ -135,7 +142,7 @@ class SinkRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
     mScreen.attach(mTexture,mEffects,mMesh);
 
     VertexEffectSink.enable();
-    DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+    DistortedLibrary.onSurfaceCreated(this);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -144,4 +151,32 @@ class SinkRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
     {
     android.util.Log.e("Sink", ex.getMessage() );
     }
-  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int openGlVersion()
+    {
+    Context context = mView.getContext();
+    final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+    final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+    int glESversion = configurationInfo.reqGlEsVersion;
+    int major = glESversion >> 16;
+    int minor = glESversion & 0xff;
+
+    return 100*major + 10*minor;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public InputStream localFile(int fileID)
+    {
+    return mResources.openRawResource(fileID);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void logMessage(String message)
+    {
+    android.util.Log.e("Sink", message );
+    }
+}
diff --git a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
index af8f714..d647a8d 100644
--- a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
+++ b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
@@ -44,6 +44,10 @@ import org.distorted.library.main.DistortedLibrary;
 import org.distorted.library.main.DistortedTexture;
 import org.distorted.library.main.DistortedEffects;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
@@ -54,7 +58,7 @@ import android.opengl.GLSurfaceView;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.ExceptionListener
+class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener, DistortedLibrary.LibraryUser
   {
   private final String[] mGFFAString = 
          
@@ -104,16 +108,17 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener, Distor
   private final float CRAWL_ANGLE = -30.0f;
   private final float FOV_ANGLE   =  60.0f;
 
-  private GLSurfaceView mView;
+  private final GLSurfaceView mView;
+  private final DistortedEffects mGFFAEffects, mLogoEffects, mCrawlEffects, mCrawlBackgroundEffects;
+  private final DistortedEffects[] mStarEffects;
+  private final DistortedScreen mScreen;
+  private final MeshQuad mQuad;
+  private final Random mRnd = new Random(0);
+  private final Resources mResources;
+
   private DistortedTexture mGFFATexture, mLogoTexture, mCrawlTexture, mCrawlBackgroundTexture, mStarTexture;
-  private DistortedEffects mGFFAEffects, mLogoEffects, mCrawlEffects, mCrawlBackgroundEffects;
-  private DistortedEffects[] mStarEffects;
   private DistortedNode mBackground;
-  private DistortedScreen mScreen;
-  private MeshQuad mQuad;
-
   private long alphaEffectID, scaleEffectID, moveEffectID;
-  private Random mRnd = new Random(0);
   private int mWidth, mHeight;
   private float mLogoRatio;
   private int mCrawlBackgroundW, mCrawlBackgroundH;
@@ -123,6 +128,7 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener, Distor
   StarWarsRenderer(GLSurfaceView v)
     {
     mView = v;
+    mResources = v.getResources();
 
     mQuad = new MeshQuad();
 
@@ -187,14 +193,7 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener, Distor
     {
     setupBitmaps();
     FragmentEffectAlpha.enable();
-    DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void distortedException(Exception ex)
-    {
-    android.util.Log.e("StarWars", ex.getMessage() );
+    DistortedLibrary.onSurfaceCreated(this);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -434,4 +433,39 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener, Distor
       mCrawlBackgroundTexture.markForDeletion();
       }
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void distortedException(Exception ex)
+    {
+    android.util.Log.e("StarWars", ex.getMessage() );
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int openGlVersion()
+    {
+    Context context = mView.getContext();
+    final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+    final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+    int glESversion = configurationInfo.reqGlEsVersion;
+    int major = glESversion >> 16;
+    int minor = glESversion & 0xff;
+
+    return 100*major + 10*minor;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public InputStream localFile(int fileID)
+    {
+    return mResources.openRawResource(fileID);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void logMessage(String message)
+    {
+    android.util.Log.e("StarWars", message );
+    }
   }
diff --git a/src/main/java/org/distorted/examples/stencil/StencilRenderer.java b/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
index a9a6cc0..2b70a82 100644
--- a/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
+++ b/src/main/java/org/distorted/examples/stencil/StencilRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.stencil;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLES31;
@@ -50,13 +54,14 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class StencilRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class StencilRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
-    private GLSurfaceView mView;
-    private DistortedScreen mScreen;
-    private DistortedTexture mCubeTex, mFloorTex, mFBOTex;
-    private DistortedNode mCube1Node, mCube2Node, mFloorNode, mFBONode;
-    private Static3D mScale, mFBOScale;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedScreen mScreen;
+    private final DistortedTexture mCubeTex, mFloorTex, mFBOTex;
+    private final DistortedNode mCube1Node, mCube2Node, mFloorNode, mFBONode;
+    private final Static3D mScale, mFBOScale;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -85,6 +90,7 @@ class StencilRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
     StencilRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
 
       MeshCubes cube   = new MeshCubes(1,1,1);
       MeshQuad  quaFlo = new MeshQuad();
@@ -218,7 +224,7 @@ class StencilRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
           {
           is.close();
           }
-        catch(IOException e) { }
+        catch(IOException ignored) { }
         }
 
       mCubeTex.setTexture(bitmap);
@@ -226,7 +232,7 @@ class StencilRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
 
       VertexEffectScale.enable();
       FragmentEffectBrightness.enable();
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -235,4 +241,32 @@ class StencilRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
       {
       android.util.Log.e("Stencil", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Stencil", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/surfaceview/RenderThread.java b/src/main/java/org/distorted/examples/surfaceview/RenderThread.java
index 3196a0b..a510ae5 100644
--- a/src/main/java/org/distorted/examples/surfaceview/RenderThread.java
+++ b/src/main/java/org/distorted/examples/surfaceview/RenderThread.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.surfaceview;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.EGL14;
@@ -47,7 +51,7 @@ import java.io.InputStream;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class RenderThread extends Thread implements DistortedLibrary.ExceptionListener
+class RenderThread extends Thread implements DistortedLibrary.LibraryUser
   {
   private static final String TAG = "RenderThread";
 
@@ -58,19 +62,21 @@ class RenderThread extends Thread implements DistortedLibrary.ExceptionListener
 
   // Used to wait for the thread to start.
   private final Object mStartLock = new Object();
-  private boolean mReady = false;
-  private volatile SurfaceHolder mSurfaceHolder;  // may be updated by UI thread
+  private final Static3D mScale;
+  private final DistortedEffects mEffects;
+  private final DistortedScreen mScreen;
+  private final SurfaceView mView;
+  private final Resources mResources;
+
   private EglCore eglCore;
   private EGLSurface eglSurface;
-
-  private DistortedEffects mEffects;
   private DistortedTexture mTexture;
   private MeshSquare mMesh;
-  private DistortedScreen mScreen;
-  private SurfaceView mView;
-  private static boolean resourcesCreated = false;
-  private Static3D mScale;
+  private volatile SurfaceHolder mSurfaceHolder;  // may be updated by UI thread
   private float mBmpRatio;
+  private boolean mReady = false;
+
+  private static boolean resourcesCreated = false;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -78,6 +84,7 @@ class RenderThread extends Thread implements DistortedLibrary.ExceptionListener
     {
     mSurfaceHolder = holder;
     mView = view;
+    mResources = view.getResources();
 
     Static3D pLeft = new Static3D( ( 90-320*0.5f)/320.0f, (108-366*0.5f)/366.0f, 0);
     Static3D pRight= new Static3D( (176-320*0.5f)/320.0f, (111-366*0.5f)/366.0f, 0);
@@ -174,7 +181,7 @@ class RenderThread extends Thread implements DistortedLibrary.ExceptionListener
           {
           mStartLock.wait();
           }
-        catch (InterruptedException ie) {  }
+        catch (InterruptedException ignored) {  }
         }
       }
     }
@@ -239,7 +246,7 @@ class RenderThread extends Thread implements DistortedLibrary.ExceptionListener
         {
         is.close();
         }
-      catch(IOException io) {}
+      catch(IOException ignored) {}
       }
 
     mBmpRatio = (float)bmp.getHeight()/bmp.getWidth();
@@ -253,14 +260,7 @@ class RenderThread extends Thread implements DistortedLibrary.ExceptionListener
     mScreen.attach(mTexture,mEffects,mMesh);
 
     VertexEffectDistort.enable();
-    DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void distortedException(Exception ex)
-    {
-    android.util.Log.e("SurfaceView", ex.getMessage() );
+    DistortedLibrary.onSurfaceCreated(this);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -287,4 +287,38 @@ class RenderThread extends Thread implements DistortedLibrary.ExceptionListener
     eglCore.swapBuffers(eglSurface);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void distortedException(Exception ex)
+    {
+    android.util.Log.e("SurfaceView", ex.getMessage() );
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int openGlVersion()
+    {
+    Context context = mView.getContext();
+    final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+    final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+    int glESversion = configurationInfo.reqGlEsVersion;
+    int major = glESversion >> 16;
+    int minor = glESversion & 0xff;
+
+    return 100*major + 10*minor;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public InputStream localFile(int fileID)
+    {
+    return mResources.openRawResource(fileID);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void logMessage(String message)
+    {
+    android.util.Log.e("SurfaceView", message );
+    }
   }
diff --git a/src/main/java/org/distorted/examples/transparency/TransparencyRenderer.java b/src/main/java/org/distorted/examples/transparency/TransparencyRenderer.java
index ad1ee59..9b81a7f 100644
--- a/src/main/java/org/distorted/examples/transparency/TransparencyRenderer.java
+++ b/src/main/java/org/distorted/examples/transparency/TransparencyRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.transparency;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.opengl.GLSurfaceView;
 
 import org.distorted.library.effect.FragmentEffectAlpha;
@@ -38,12 +42,14 @@ import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
+import java.io.InputStream;
+
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class TransparencyRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class TransparencyRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private static final int NUM = 4; // 4 ints (x,y,z, argb) each describe 1 object below
 
@@ -56,16 +62,17 @@ class TransparencyRenderer implements GLSurfaceView.Renderer, DistortedLibrary.E
     private static final int NUM_OBJECTS = OBJECTS.length/NUM;
     private static final int OBJ_SIZE    = 100;
 
-    private GLSurfaceView mView;
-    private DistortedNode[] mNode;
-    private DistortedTexture[] mTex;
-    private Static3D[]  mMoveVector;
-    private Static1D[]  mAlphaVector;
-    private DistortedScreen mScreen;
-    private Static3D mScale;
-    private PostprocessEffectBlur[] mBlur;
-    private boolean[] mBlurApplied;
-    private DistortedEffects[] mEffects;
+    private final GLSurfaceView mView;
+    private final Resources mResources;
+    private final DistortedNode[] mNode;
+    private final DistortedTexture[] mTex;
+    private final Static3D[]  mMoveVector;
+    private final Static1D[]  mAlphaVector;
+    private final DistortedScreen mScreen;
+    private final Static3D mScale;
+    private final PostprocessEffectBlur[] mBlur;
+    private final boolean[] mBlurApplied;
+    private final DistortedEffects[] mEffects;
 
     Static4D mQuat1, mQuat2;
     int mScreenMin;
@@ -75,6 +82,7 @@ class TransparencyRenderer implements GLSurfaceView.Renderer, DistortedLibrary.E
     TransparencyRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
 
       MeshSquare mesh = new MeshSquare(1,1);
 
@@ -215,7 +223,7 @@ class TransparencyRenderer implements GLSurfaceView.Renderer, DistortedLibrary.E
       VertexEffectScale.enable();
       PostprocessEffectBlur.enable();
       FragmentEffectAlpha.enable();
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -224,4 +232,32 @@ class TransparencyRenderer implements GLSurfaceView.Renderer, DistortedLibrary.E
       {
       android.util.Log.e("Transparency", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Transparency", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java b/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java
index 2ba1e8f..8a506eb 100644
--- a/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java
+++ b/src/main/java/org/distorted/examples/triblur/TriblurRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.triblur;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -40,7 +44,6 @@ import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedNode;
 import org.distorted.library.main.DistortedScreen;
 import org.distorted.library.main.DistortedTexture;
-import org.distorted.library.mesh.MeshBase;
 import org.distorted.library.mesh.MeshCubes;
 import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static2D;
@@ -55,7 +58,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
     private static final int[][] OBJECTS =
         {
@@ -68,6 +71,7 @@ class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
     private static final int OBJ_SIZE    = 100;
 
     private final GLSurfaceView mView;
+    private final Resources mResources;
     private final DistortedTexture mTex;
     private final DistortedNode[] mNode;
     private final Static2D[] mEffectHaloRadius;
@@ -89,6 +93,7 @@ class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
     TriblurRenderer(GLSurfaceView v)
       {
       mView = v;
+      mResources = v.getResources();
 
       MeshCubes mesh = new MeshCubes(1,1,1);
 
@@ -222,14 +227,7 @@ class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
       FragmentEffectChroma.enable();
       Effect.enableEffects(EffectType.POSTPROCESS);
 
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void distortedException(Exception ex)
-      {
-      android.util.Log.e("Triblur", ex.getMessage() );
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -271,4 +269,39 @@ class TriblurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Except
         android.util.Log.e("renderer", "Error, number: "+object+" effect: "+effect );
         }
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void distortedException(Exception ex)
+      {
+      android.util.Log.e("Triblur", ex.getMessage() );
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Triblur", message );
+      }
 }
diff --git a/src/main/java/org/distorted/examples/wind/WindRenderer.java b/src/main/java/org/distorted/examples/wind/WindRenderer.java
index aa8b1e5..02eb949 100644
--- a/src/main/java/org/distorted/examples/wind/WindRenderer.java
+++ b/src/main/java/org/distorted/examples/wind/WindRenderer.java
@@ -19,6 +19,10 @@
 
 package org.distorted.examples.wind;
 
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
@@ -46,25 +50,27 @@ import javax.microedition.khronos.opengles.GL10;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class WindRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+class WindRenderer implements GLSurfaceView.Renderer, DistortedLibrary.LibraryUser
 {
    private static final int X = 50;
    private static final int Y = 30;
    private static final int Z =  1;
 
-   private GLSurfaceView mView;
-   private DistortedTexture mTexture;
-   private DistortedScreen mScreen;
-   private WindEffectsManager mManager;
-   private WindGust mGust;
-   private Static3D mMove, mScale;
-   private float mObjWidth, mObjHeight;
+   private final GLSurfaceView mView;
+   private final Resources mResources;
+   private final DistortedTexture mTexture;
+   private final DistortedScreen mScreen;
+   private final WindEffectsManager mManager;
+   private final WindGust mGust;
+   private final Static3D mMove, mScale;
+   private final float mObjWidth, mObjHeight;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    WindRenderer(GLSurfaceView view)
       { 
       mView = view;
+      mResources = view.getResources();
 
       MeshCubes cubes = new MeshCubes(X,Y,Z);
       DistortedEffects effects = new DistortedEffects();
@@ -133,7 +139,7 @@ class WindRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
     
    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       {
-      int min = width<height? width:height;
+      int min = Math.min(width,height);
 
       float factor = ((float)min)/(mObjHeight + 1.4f*mObjWidth);
       mMove.set( factor*mObjHeight*1.28f -min*0.5f, min*0.5f - factor*mObjHeight*0.58f, 0 );
@@ -158,7 +164,7 @@ class WindRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
           {
           is.close();
           }
-        catch(IOException e) { }
+        catch(IOException ignored) { }
         }
 
       mTexture.setTexture(bitmap);
@@ -166,7 +172,7 @@ class WindRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
       VertexEffectScale.enable();
       VertexEffectDeform.enable();
       VertexEffectWave.enable();
-      DistortedLibrary.onSurfaceCreated(mView.getContext(), this);
+      DistortedLibrary.onSurfaceCreated(this);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -175,4 +181,32 @@ class WindRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
       {
       android.util.Log.e("Wind", ex.getMessage() );
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int openGlVersion()
+      {
+      Context context = mView.getContext();
+      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+      int glESversion = configurationInfo.reqGlEsVersion;
+      int major = glESversion >> 16;
+      int minor = glESversion & 0xff;
+
+      return 100*major + 10*minor;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public InputStream localFile(int fileID)
+      {
+      return mResources.openRawResource(fileID);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void logMessage(String message)
+      {
+      android.util.Log.e("Wind", message );
+      }
 }
