<html>
<body>
  <div id="body" style="background-color:#ffffff;" >
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head" style="border-bottom-width:1px;border-bottom-style:solid;" ><td class="headtd" style="padding:0;padding-top:.2em;" colspan="4">Commit in <b><tt>lxdream</tt></b></td></tr>
<tr><td><tt>android/src/org/lxdream/<a href="#file1">Dreamcast.java</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+3</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4dff831f1a2e -> 83b15705cdde</td></tr>
<tr class="alt" style=";" ><td><tt>                       /<a href="#file2">LxdreamActivity.java</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+2</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-1</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4dff831f1a2e -> 83b15705cdde</td></tr>
<tr><td><tt>src/drivers/<a href="#file3">video_egl.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+9</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-3</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4dff831f1a2e -> 83b15705cdde</td></tr>
<tr class="alt" style=";" ><td><tt>src/<a href="#file4">gui_android.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+33</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-5</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4dff831f1a2e -> 83b15705cdde</td></tr>
<tr><td><tt>src/pvr2/<a href="#file5">glrender.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+5</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4dff831f1a2e -> 83b15705cdde</td></tr>
<tr class="alt" style=";" ><td><tt>        /<a href="#file6">glutil.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+8</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4dff831f1a2e -> 83b15705cdde</td></tr>
<tr><td><tt>        /<a href="#file7">glutil.h</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+1</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4dff831f1a2e -> 83b15705cdde</td></tr>
<tr class="alt" style=";" ><td><tt>        /<a href="#file8">pvr2.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+4</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-2</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4dff831f1a2e -> 83b15705cdde</td></tr>
<tr><td><tt>        /<a href="#file9">texcache.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+131</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-46</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">4dff831f1a2e -> 83b15705cdde</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+196</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-57</td><td></td></tr>
</table>
<small id="info" style="color: #888888;" >9 modified files</small><br />
<pre class="comment" style="white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd;" >
More android WIP
  - Implement onPause/onResume (although resume is not actually working yet)
  - Implement BGRA => RGBA texture conversion (BGRA doesn't seem to work on the TFP)

Boot swirl is now displayed, albeit depth buffering seems to be broken.
</pre>
<hr /><a name="file1" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/android/src/org/lxdream</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>Dreamcast.java</b></big> <small id="info" style="color: #888888;" >4dff831f1a2e -> 83b15705cdde</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/android/src/org/lxdream/Dreamcast.java
+++ lxdream/android/src/org/lxdream/Dreamcast.java
@@ -33,6 +33,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >      public static native boolean isRunnable();
      public static native boolean isRunning();
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     public static native void onAppPause();
+     public static native void onAppResume();
+     
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >      /* GD-Rom */
      public static native boolean mount( String filename );
      public static native void unmount();
</pre></div>
<hr /><a name="file2" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/android/src/org/lxdream</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>LxdreamActivity.java</b></big> <small id="info" style="color: #888888;" >4dff831f1a2e -> 83b15705cdde</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/android/src/org/lxdream/LxdreamActivity.java
+++ lxdream/android/src/org/lxdream/LxdreamActivity.java
@@ -63,12 +63,13 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     @Override 
     protected void onPause() {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        Dreamcast.onAppPause();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         super.onPause();
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        Dreamcast.stop();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
     @Override 
     protected void onResume() {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     Dreamcast.onAppResume();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         super.onResume();
     }
     
</pre></div>
<hr /><a name="file3" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/drivers</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>video_egl.c</b></big> <small id="info" style="color: #888888;" >4dff831f1a2e -> 83b15705cdde</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/drivers/video_egl.c
+++ lxdream/src/drivers/video_egl.c
@@ -76,7 +76,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         EGL_CONTEXT_CLIENT_VERSION, 2,
         EGL_NONE, EGL_NONE };
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static EGLDisplay display;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static EGLDisplay display = EGL_NO_DISPLAY;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > static EGLContext context = EGL_NO_CONTEXT;
 static EGLSurface surface = EGL_NO_SURFACE;
 static gboolean fbo_created = FALSE;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -117,6 +117,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
     if( eglMakeCurrent( display, surface, surface, context ) == EGL_FALSE ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        logEGLError( "Unable to make EGL context current" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         video_egl_clear_window();
         return FALSE;
     }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -129,13 +130,14 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     fbo_created = TRUE;
     gl_set_video_size(width, height, 0);
     pvr2_setup_gl_context();
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    INFO( "Initialised EGL %d.%d<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >\n</span>", major, minor );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    INFO( "Initialised EGL %d.%d", major, minor );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return TRUE;
 }
 
 void video_egl_clear_window()
 {
     if( fbo_created ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        pvr2_shutdown_gl_context();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         gl_fbo_shutdown();
         fbo_created = FALSE;
     }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -148,7 +150,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         eglDestroyContext(display, context);
         context = EGL_NO_CONTEXT;
     }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    eglTerminate(display);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( display != EGL_NO_DISPLAY ) {
+        eglTerminate(display);
+        display = EGL_NO_DISPLAY;
+    }
+    INFO( "Terminated EGL" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 static void video_egl_swap_buffers()
</pre></div>
<hr /><a name="file4" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>gui_android.c</b></big> <small id="info" style="color: #888888;" >4dff831f1a2e -> 83b15705cdde</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/gui_android.c
+++ lxdream/src/gui_android.c
@@ -45,7 +45,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     int width, height, format;
 };
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static struct surface_info current_surface;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static struct surface_info current_surface<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" > = { NULL, 0, 0, 0 }</span>;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > static const char *appHome = NULL;
 
 /**
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -89,14 +89,30 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return 0;
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+int android_do_pause(void *data)
+{
+    if( dreamcast_is_running() ) {
+        dreamcast_stop();
+    }
+    video_egl_clear_window();
+    INFO( "Paused" );
+    return 0;
+}
+
+int android_do_resume(void *data)
+{
+    struct surface_info *surface = (struct surface_info *)data;
+    if( surface->win != NULL )
+        video_egl_set_window(surface->win, surface->width, surface->height, surface->format);
+    INFO( "Resumed" );
+    return 0;
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > int android_clear_surface(void *data)
 {
     struct surface_info *surface = (struct surface_info *)data;
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( dreamcast_is_running() ) {
-        dreamcast_stop();
-    }
-    video_egl_clear_window();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    android_do_pause(data); /* If we haven't already stopped, stop now */
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     ANativeWindow_release(surface->win);
     surface->win = NULL;
     return 0;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -287,6 +303,17 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     tqueue_send_message( android_callback_wrapper, dreamcast_stop );
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+JNIEXPORT void JNICALL Java_org_lxdream_Dreamcast_onAppPause(JNIEnv * env, jclass obj)
+{
+    /* Need to make sure this completely shuts down before we return */
+    tqueue_send_message( android_do_pause, &current_surface );
+}
+
+JNIEXPORT void JNICALL Java_org_lxdream_Dreamcast_onAppResume(JNIEnv * env, jclass obj)
+{
+    tqueue_post_message( android_do_resume, &current_surface );
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > JNIEXPORT jboolean JNICALL Java_org_lxdream_Dreamcast_isRunning(JNIEnv *env, jclass obj)
 {
     return dreamcast_is_running();
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -322,6 +349,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     } else {
         current_surface.format = COLFMT_RGB888;
     }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    INFO( "Setting surface" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     tqueue_post_message( android_set_surface, &current_surface );
 }
 
</pre></div>
<hr /><a name="file5" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>glrender.c</b></big> <small id="info" style="color: #888888;" >4dff831f1a2e -> 83b15705cdde</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/glrender.c
+++ lxdream/src/pvr2/glrender.c
@@ -150,6 +150,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glClearStencil(0);
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+void pvr2_shutdown_gl_context()
+{
+    texcache_gl_shutdown();
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * Setup the basic context that's shared between normal and modified modes -
  * depth, culling
</pre></div>
<hr /><a name="file6" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>glutil.c</b></big> <small id="info" style="color: #888888;" >4dff831f1a2e -> 83b15705cdde</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/glutil.c
+++ lxdream/src/pvr2/glutil.c
@@ -49,6 +49,14 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return isGLExtensionSupported("GL_ARB_texture_mirrored_repeat");
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean isGLBGRATextureSupported()
+{
+    /* Note: e.g. Tegra 3 reports GL_EXT_bgra, but it doesn't actually work.
+     * Need to check this with NVIDIA, in meantime assume GLES2 doesn't have
+     * BGRA support */
+    return !isOpenGLES2() && isGLExtensionSupported("GL_EXT_bgra");
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 gboolean isGLShaderSupported()
 {
</pre></div>
<hr /><a name="file7" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>glutil.h</b></big> <small id="info" style="color: #888888;" >4dff831f1a2e -> 83b15705cdde</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/glutil.h
+++ lxdream/src/pvr2/glutil.h
@@ -56,6 +56,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > gboolean isGLPixelBufferSupported();
 gboolean isGLMultitextureSupported();
 gboolean isGLMirroredTextureSupported();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean isGLBGRATextureSupported();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > gboolean isGLShaderSupported();
 GLint glGetMaxColourAttachments();
 
</pre></div>
<hr /><a name="file8" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>pvr2.h</b></big> <small id="info" style="color: #888888;" >4dff831f1a2e -> 83b15705cdde</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/pvr2.h
+++ lxdream/src/pvr2/pvr2.h
@@ -279,6 +279,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
 void pvr2_setup_gl_context();
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+void pvr2_shutdown_gl_context();
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void render_backplane( uint32_t *polygon, uint32_t width, uint32_t height, uint32_t mode );
 
 void render_autosort_tile( pvraddr_t tile_entry, int render_mode );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -320,10 +322,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /**
  * Flush all textures and delete. The cache will be non-functional until
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * the next call to texcache_init(). This would typically be done if
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * the next call to texcache_<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >gl_</span>init(). This would typically be done if
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * switching GL targets.
  */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-void texcache_shutdown( void );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+void texcache_<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >gl_</span>shutdown( void );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /**
  * Flush (ie free) all textures.
</pre></div>
<hr /><a name="file9" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>texcache.c</b></big> <small id="info" style="color: #888888;" >4dff831f1a2e -> 83b15705cdde</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/texcache.c
+++ lxdream/src/pvr2/texcache.c
@@ -61,6 +61,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > static uint32_t texcache_palette_mode;
 static uint32_t texcache_stride_width;
 static gboolean texcache_have_palette_shader;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static gboolean texcache_have_bgra;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > static gboolean texcache_palette_valid;
 static GLuint texcache_palette_texid;
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -85,41 +86,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     texcache_stride_width = 0;
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-/**
- * Setup the initial texture ids (must be called after the GL context is
- * prepared)
- */
-void texcache_gl_init( )
-{
-    int i;
-    GLuint texids[MAX_TEXTURES];
-
-    if( display_driver->capabilities.has_sl ) {
-        texcache_have_palette_shader = TRUE;
-        texcache_palette_valid = FALSE;
-        glGenTextures(1, &texcache_palette_texid );
-
-        /* Bind the texture and set the params */
-        glActiveTexture(GL_TEXTURE1);
-        glBindTexture(GL_TEXTURE_2D, texcache_palette_texid);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
-        glActiveTexture(GL_TEXTURE0);
-
-    } else {
-        texcache_have_palette_shader = FALSE;
-    }
-
-    glGenTextures( MAX_TEXTURES, texids );
-    for( i=0; i<MAX_TEXTURES; i++ ) {
-        texcache_active_list[i].texture_id = texids[i];
-    }
-}
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 void texcache_release_render_buffer( render_buffer_t buffer )
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( !buffer->flushed )<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" > </span>
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( !buffer->flushed )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         pvr2_render_buffer_copy_to_sh4(buffer);
     pvr2_destroy_render_buffer(buffer);
 }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -148,21 +118,59 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 /**
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Setup the initial texture ids (must be called after the GL context is
+ * prepared)
+ */
+void texcache_gl_init( )
+{
+    int i;
+    GLuint texids[MAX_TEXTURES];
+
+    if( display_driver->capabilities.has_sl ) {
+        texcache_have_palette_shader = TRUE;
+        texcache_palette_valid = FALSE;
+        glGenTextures(1, &texcache_palette_texid );
+
+        /* Bind the texture and set the params */
+        glActiveTexture(GL_TEXTURE1);
+        glBindTexture(GL_TEXTURE_2D, texcache_palette_texid);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+        glActiveTexture(GL_TEXTURE0);
+
+    } else {
+        texcache_have_palette_shader = FALSE;
+    }
+    texcache_have_bgra = isGLBGRATextureSupported();
+
+    glGenTextures( MAX_TEXTURES, texids );
+    for( i=0; i<MAX_TEXTURES; i++ ) {
+        texcache_active_list[i].texture_id = texids[i];
+    }
+    INFO( "Texcache initialized (%s, %s)", (texcache_have_palette_shader ? "Palette shader" : "No palette support"),
+            (texcache_have_bgra ? "BGRA" : "RGBA") );
+}
+
+/**
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * Flush all textures and delete. The cache will be non-functional until
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * the next call to texcache_init(). This would typically be done if
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * the next call to texcache_<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >gl_</span>init(). This would typically be done if
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * switching GL targets.
  */    
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-void texcache_shutdown( )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+void texcache_<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >gl_</span>shutdown( )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     GLuint texids[MAX_TEXTURES];
     int i;
     texcache_flush();
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( texcache_have_palette_shader )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( texcache_have_palette_shader )<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" > {</span>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         glDeleteTextures( 1, &texcache_palette_texid );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        texcache_palette_texid = -1;
+    }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     for( i=0; i<MAX_TEXTURES; i++ ) {
         texids[i] = texcache_active_list[i].texture_id;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        texcache_active_list[i].texture_id = -1;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
     glDeleteTextures( MAX_TEXTURES, texids );
 }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -244,6 +252,73 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 /**
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Convert BGRA data in buffer to RGBA format (for systems that don't natively
+ * support BGRA).
+ * @return converted format type
+ * @param data BGRA pixel data
+ * @param nPixels total number of pixels (width*height)
+ * @param glFormatType GL format of source data. One of
+ *    GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_SHORT_4_4_4_4_REV, or GL_UNSIGNED_BYTE
+ */
+static int bgra_to_rgba( unsigned char *data, unsigned nPixels, int glFormatType )
+{
+    unsigned i;
+    switch( glFormatType ) {
+    case GL_UNSIGNED_SHORT_1_5_5_5_REV: {
+        uint16_t *p = (uint16_t *)data;
+        uint16_t *end = p + nPixels;
+        while( p != end ) {
+            uint16_t v = *p;
+            *p = (v >> 15) | (v<<1);
+            p++;
+        }
+        return GL_UNSIGNED_SHORT_5_5_5_1;
+    }
+    case GL_UNSIGNED_SHORT_4_4_4_4_REV: { /* ARGB => RGBA */
+        uint16_t *p = (uint16_t *)data;
+        uint16_t *end = p + nPixels;
+        while( p != end ) {
+            uint16_t v = *p;
+            *p = (v >> 12) | (v<<4);
+            p++;
+        }
+        return GL_UNSIGNED_SHORT_4_4_4_4;
+    }
+    case GL_UNSIGNED_BYTE: { /* ARGB => ABGR */
+        uint32_t *p = (uint32_t *)data;
+        uint32_t *end = p + nPixels;
+        while( p != end ) {
+            uint32_t v = *p;
+            *p = (v&0xFF000000) | ((v<<16) & 0x00FF0000) | (v & 0x0000FF00) | ((v>>16) & 0x000000FF);
+            p++;
+        }
+        return GL_UNSIGNED_BYTE;
+    }
+    default:
+        assert( 0 && "Unsupported BGRA format" );
+        return glFormatType;
+    }
+}
+
+/**
+ * Install the image data in the currently bound 2D texture.
+ * May modify the buffered data if needed to make the texture compatible with
+ * the GL.
+ */
+static void texcache_load_image_2D( int level, GLint intFormat, int width, int height, GLint format, GLint type, unsigned char *data )
+{
+    if( format == GL_BGRA && !texcache_have_bgra ) {
+        GLint rgbaType = bgra_to_rgba( data, width*height, type );
+        glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, GL_RGBA, rgbaType,
+                data );
+    } else {
+        glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, format, type,
+                data );
+    }
+
+}
+
+/**
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * Load the palette into 4 textures of 256 entries each. This mirrors the
  * banking done by the PVR2 for 8-bit textures, and also ensures that we
  * can use 8-bit paletted textures ourselves.
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -254,7 +329,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     unsigned i;
     int bpp = 2;
     uint32_t *palette = (uint32_t *)mmio_region_PVR2PAL.mem;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    uint16_t packed_palette[1024];
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    char buf[4096];
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     char *data = (char *)palette;
 
     switch( texcache_palette_mode ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -280,13 +355,21 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         break; /* Can't happen */
     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( bpp == 2 ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        data = buf;
+        uint16_t *packed_palette = (uint16_t *)buf;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         for( i=0; i<1024; i++ ) {
             packed_palette[i] = (uint16_t)palette[i];
         }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        data = (char *)packed_palette;
-
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        if( !texcache_have_bgra && format == GL_BGRA ) {
+            type = bgra_to_rgba(data, 1024, type);
+            format = GL_RGBA;
+        }
+    } else if( !texcache_have_bgra && format == GL_BGRA ) { /* bpp == 4 */
+        data = buf;
+        memcpy( buf, palette, 4096 );
+        type = bgra_to_rgba(buf, 1024, type);
+        format = GL_RGBA;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
     glActiveTexture(GL_TEXTURE1);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -448,7 +531,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( r > 255 ) { r = 255; } else if( r < 0 ) { r = 0; }
     if( g > 255 ) { g = 255; } else if( g < 0 ) { g = 0; }
     if( b > 255 ) { b = 255; } else if( b < 0 ) { b = 0; }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    return 0xFF000000 | (r<<16) | (g<<8) | (b);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    return 0xFF000000 | (b<<16) | (g<<8) | (r);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -555,10 +638,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             break;
         case PVR2_TEX_FORMAT_YUV422:
             /* YUV422 isn't directly supported by most implementations, so decode
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-             * it to a (reasonably) standard <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >ARGB32</span>.
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+             * it to a (reasonably) standard <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >RGBA8</span>.
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >              */
             bpp_shift = 2;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            format = GL_<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >BGR</span>A;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            format = GL_<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >RGB</span>A;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             type = GL_UNSIGNED_BYTE;
             break;
         case PVR2_TEX_FORMAT_BUMPMAP:
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -577,7 +660,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         } else {
             pvr2_vram64_read_stride( data, width<<bpp_shift, texture_addr, texcache_stride_width<<bpp_shift, height );
         }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        glTexImage2D( GL_TEXTURE_2D, 0, intFormat, width, height, 0, format, type, data );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        texcache_load_image_2D( 0, intFormat, width, height, format, type, data );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_filter);
         return;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -678,11 +761,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
         /* Pass to GL */
         if( level == last_level && level != 0 ) { /* 1x1 stored within a 2x2 */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            glTexImage2D( GL_TEXTURE_2D, level, intFormat, 1, 1, 0, format, type,
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            texcache_load_image_2D( level, intFormat, 1, 1, format, type,
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                     data + (3 << bpp_shift) );
         } else {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            glTexImage2D( GL_TEXTURE_2D, level, intFormat, mip_width, mip_height, 0, format, type,
-                    data );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            texcache_load_image_2D( level, intFormat, mip_width, mip_height, format, type, data );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             if( mip_width > 2 ) {
                 mip_width >>= 1;
                 mip_height >>= 1;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -780,7 +862,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         unsigned height = POLY2_TEX_HEIGHT(poly2_word);
 
         glBindTexture( GL_TEXTURE_2D, texcache_active_list[slot].texture_id );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        glGetError();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         texcache_load_texture( texture_addr, width, height, texture_word );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        INFO( "Loaded texture %d: %x %dx%d %x (%x)", texcache_active_list[slot].texture_id, texture_addr, width, height, texture_word,
+                glGetError() );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
         /* Set texture parameters from the poly2 word */
         if( POLY2_TEX_CLAMP_U(poly2_word) ) {
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>