changeset 3148:6d36ddcd448b

Automated merge with ssh://jfxsrc.us.oracle.com//javafx/8.0/MASTER/jfx/rt
author jgodinez
date Tue, 09 Apr 2013 09:33:44 -0700
parents 17956a42070a 193cc7c25031
children fc5946a10151 223958a71bba 6fbbe378550a
files
diffstat 135 files changed, 3765 insertions(+), 776 deletions(-) [+]
line wrap: on
line diff
--- a/build.gradle	Thu Apr 04 20:11:19 2013 -0700
+++ b/build.gradle	Tue Apr 09 09:33:44 2013 -0700
@@ -23,11 +23,7 @@
  * questions.
  */
 
-import java.util.concurrent.ConcurrentHashMap
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.Executors
-import java.util.concurrent.Future
+import java.util.concurrent.*
 
 /**
  * The main build script for JavaFX.
@@ -114,7 +110,8 @@
 // These variables indicate what the platform is that is doing the build. Is
 // this build running on a Mac, Windows, or Linux machine? 32 or 64 bit?
 ext.OS_NAME = System.getProperty("os.name").toLowerCase();
-ext.IS_64 = System.getProperty("os.arch").toLowerCase().contains("64");
+ext.OS_ARCH = System.getProperty("os.arch");
+ext.IS_64 = OS_ARCH.toLowerCase().contains("64");
 ext.IS_MAC = OS_NAME.contains("mac") || OS_NAME.contains("darwin");
 ext.IS_WINDOWS = OS_NAME.contains("windows");
 ext.IS_LINUX = OS_NAME.contains("linux");
@@ -249,6 +246,7 @@
 
 // Log some of the settings we've determined. We could log more here, it doesn't really hurt.
 logger.info("OS_NAME: $OS_NAME");
+logger.info("OS_ARCH: $OS_ARCH");
 logger.info("JAVA_HOME: $JAVA_HOME");
 logger.info("JDK_HOME: $JDK_HOME");
 logger.info("BINARY_STUB: ${file(BINARY_STUB)}");
@@ -424,10 +422,9 @@
 }
 
 class CompileResourceTask extends NativeCompileTask {
-
     protected File outputFile(File sourceFile) {
         final String outFileName = sourceFile.getName().substring(0, sourceFile.getName().lastIndexOf("."));
-        new File("$output/${outFileName}.res");
+        return new File("$output/${outFileName}.res");
     }
 
     protected void doCompile(File sourceFile, File outputFile){
@@ -453,7 +450,10 @@
 
 class CCTask extends NativeCompileTask {
     @Optional String compiler;
-    @InputDirectory File headers;
+    @Optional List<String> linkerOptions = new ArrayList<String>();
+    @Optional @InputDirectory File headers;
+    @Optional Closure eachOutputFile; // will be given a File and must return a File
+    @Optional boolean exe = false;
 
     protected File outputFile(File sourceFile) {
         final String outFileName = sourceFile.getName().substring(0, sourceFile.getName().lastIndexOf("."));
@@ -461,13 +461,19 @@
     }
 
     protected void doCompile(File sourceFile, File outputFile) {
+        if (eachOutputFile != null) {
+            outputFile = eachOutputFile(outputFile);
+        }
+
         // or compile sources using CC
-        final File pdbFile = new File("$output/${outputFile.name.replace('.obj', '.pdb')}");
+        final int lastDot = outputFile.name.lastIndexOf(".");
+        final File pdbFile = new File("$output/${lastDot > 0 ? outputFile.name.substring(0, lastDot) + '.pdb' : outputFile.name + '.pdb'}");
 
         // TODO the PDB file is never being built -- maybe because it is only built during
         // debug builds, otherwise that flag is ignored "/Fd" or "-Fd"
         project.exec({
-            commandLine("${compiler == null ? project.CC : compiler}", "-I$headers");
+            commandLine("${compiler == null ? project.CC : compiler}");
+            if (headers != null) args("-I$headers");
 
             // Add the source roots in as include directories
             sourceRoots.each { root ->
@@ -489,11 +495,23 @@
 
             // Add the name of the source file to compile
             if (project.IS_WINDOWS) {
-                args("/Fd$pdbFile", "/Fo$outputFile", "$sourceFile");
+                if (exe) {
+                    final File exeFile = new File("$output/${lastDot > 0 ? outputFile.name.substring(0, lastDot) + '.exe' : outputFile.name + '.exe'}");
+                    args(/*"/Fd$pdbFile",*/ "/Fo$outputFile", "/Fe$exeFile", "$sourceFile")
+                } else {
+                    args(/*"/Fd$pdbFile",*/ "/Fo$outputFile", "$sourceFile");
+                }
             } else {
                 args("-Fd$pdbFile", "-o", "$outputFile", "$sourceFile");
             }
 
+            // Add any optional linker options -- used now rarely but can be
+            // used for any cc task which isn't going to be followed by a
+            // link task
+            if (linkerOptions != null && !linkerOptions.isEmpty()) {
+                args(linkerOptions);
+            }
+
             if (project.IS_WINDOWS){
                 environment(project.WINDOWS_NATIVE_COMPILE_ENVIRONMENT);
             }
@@ -577,7 +595,7 @@
 allprojects {
     // We want to configure all projects as java projects and use the same compile settings
     // etc, except for the root project which we just want to ignore
-    if (project == rootProject) return
+    if (project == rootProject || project.name == "deployment") return
     // All of our projects are java projects
     apply plugin: "java"
     sourceCompatibility = 1.7
@@ -599,7 +617,8 @@
         // compiler stuff because otherwise it won't compile on CYGWIN
         // TODO need to file issue with Gradle
         compile.options.useAnt = true
-        compile.options.debug = IS_DEBUG
+        compile.options.debug = true // we always generate debugging info in the class files
+        compile.options.debugOptions.debugLevel = IS_DEBUG ? "source,lines,vars" : "source,lines"
         compile.options.fork = true
         compile.options.forkOptions.executable = JAVAC
         compile.options.warnings = IS_LINT
@@ -607,40 +626,19 @@
         // Note that the compileFooJava task is automatically created whenever a source set is
         // defined. So the "test" source set automatically creates a "compileTestJava" task (among others).
         if (name == "compileTestJava") {
-            compile.options.compilerArgs = ["-Djava.ext.dirs=", "-XDignore.symbol.file"]
+            compile.options.compilerArgs = ["-Djava.ext.dirs=", "-XDignore.symbol.file", "-encoding","UTF-8"]
             classpath = sourceSets.test.compileClasspath + rootProject.files(rootProject.BINARY_STUB)
         } else if (name == "compileStubJava") {
-            compile.options.compilerArgs = ["-Djava.ext.dirs=", "-XDignore.symbol.file"]
+            compile.options.compilerArgs = ["-Djava.ext.dirs=", "-XDignore.symbol.file", "-encoding","UTF-8"]
             classpath = sourceSets.stub.compileClasspath + rootProject.files(rootProject.BINARY_STUB)
         } else {
-            compile.options.compilerArgs = ["-Djava.ext.dirs=", "-XDignore.symbol.file", "-s", "$buildDir/builder-src"]
+            compile.options.compilerArgs = ["-Djava.ext.dirs=", "-XDignore.symbol.file", "-s", "$buildDir/builder-src", "-encoding","UTF-8"]
             // Both controls & graphics need to use the annotation processor, but not the other guys.
             if (["graphics", "controls", "swing", "swt", "base", "fxml"].contains(project.name)){
                 compile.options.compilerArgs += ["-processor", "javafx.builder.processor.BuilderProcessor"]
             }
             classpath = sourceSets.main.compileClasspath + rootProject.files(rootProject.BINARY_STUB)
         }
-        doLast {
-            // Workaround: there are a number of packages which are now getting builders
-            // generated even though they they didn't before since we combined sources
-            // into fewer projects. So I have to strip out the .class files after compilation!
-            // Alternatively we can go through and add @NoBuilder to all these classes
-            // (or stop using automatic builder generation, but that's another story).
-            delete(files("$buildDir/builder-src/javafx/beans",
-                         "$buildDir/builder-src/javafx/concurrent",
-                         "$buildDir/builder-src/javafx/event",
-                         "$buildDir/builder-src/javafx/fxml",
-                         "$buildDir/builder-src/javafx/collections",
-                         "$buildDir/builder-src/javafx/util"));
-            delete(files("$buildDir/classes/main/javafx/beans",
-                         "$buildDir/classes/main/javafx/concurrent",
-                         "$buildDir/classes/main/javafx/event",
-                         "$buildDir/classes/main/javafx/fxml",
-                         "$buildDir/classes/main/javafx/collections",
-                         "$buildDir/classes/main/javafx/util").getAsFileTree().filter( { file ->
-                !file.getName().equals("Builder.class") && file.getName().endsWith("Builder.class")
-            } ));
-        }
     }
     // Setup the repositories that we'll download libraries from. Maven Central is
     // just easy for most things. The custom "ivy" repo is for downloading SWT. The way it
@@ -793,10 +791,7 @@
     sourceSets {
         main.java.srcDirs = ["src/main/java", "src/main/dt", "src/main/jsl-generator"]
         test
-        stub {
-            // The src/main/java is needed for some CSS related tests
-            resources.srcDirs = ["src/stub/resources", "src/main/java"]
-        }
+        stub
     }
 
     dependencies {
@@ -1125,6 +1120,155 @@
     classes.dependsOn copyPrismShaders
 }
 
+project(":fxpackager") {
+    // fxpackager has a dependency on ant in order to build the ant jar,
+    // and as such needs to point to the apache binary repository
+    repositories {
+        maven {
+            url "https://repository.apache.org"
+        }
+    }
+
+    dependencies {
+        compile "org.apache.ant:ant:1.8.2"
+    }
+
+    // When producing the jar, we need to relocate a few class files
+    // from their normal location to a resources/classes or resources/web-files
+    // location
+    jar {
+        includeEmptyDirs = false
+        archiveName = "ant-javafx.jar"
+        eachFile { FileCopyDetails details ->
+            if (details.path.startsWith("com/javafx/main")) {
+                details.path = "resources/classes/$details.path"
+            } else if (details.path.startsWith("web-files")) {
+                details.path = "resources/$details.path"
+            }
+        }
+    }
+
+    // The "man" task will create a $buildDir/man containing the man
+    // files for the system being built
+    task man(type: Copy) {
+        includeEmptyDirs = false
+        enabled = IS_LINUX || IS_MAC
+        from "src/main/man"
+        into "$buildDir/man"
+        exclude "**/*.html"
+        if (IS_MAC) exclude "**/ja_JP.UTF-8/**"
+    }
+    processResources.dependsOn man
+
+    // Compile the native launchers. These are included in ant-javafx.jar
+    if (IS_WINDOWS) {
+        task compileWinLauncher(type: CCTask, group: "Build") {
+            description = "Compiles native sources for the application co-bundle launcher"
+            matches = "WinLauncher\\.cpp"
+            params.addAll(["/nologo", "/W3", "/EHsc", "/D_WINDOWS",
+                    "/DUNICODE", "/D_UNICODE", "/DWIN32", "/D_LITTLE_ENDIAN", "/DWIN32_LEAN_AND_MEAN",
+                    "/I$JDK_HOME/include", "/I$JDK_HOME/include/win32", "/arch:SSE", "/fp:fast",
+                    "/O2", "/MD"])
+            output(file("$buildDir/classes/main/com/sun/javafx/tools/resource/windows"))
+            source file("src/main/native/launcher/win")
+            exe = true
+            linkerOptions.addAll(["/link", "/nologo", "/SUBSYSTEM:WINDOWS", "user32.lib", "shell32.lib", "advapi32.lib"])
+        }
+        task compileIconSwap(type: CCTask, group: "Build") {
+            description = "Compiles native sources for the application co-bundle launcher"
+            matches = "iconswap\\.cpp"
+            params.addAll(["/nologo", "/W3", "/EHsc", "/D_WINDOWS", "/DUNICODE", "/D_UNICODE",
+                    "/arch:SSE", "/fp:fast", "/O2"])
+            output(file("$buildDir/classes/main/com/sun/javafx/tools/resource/windows"))
+            source file("src/main/native/launcher/win")
+            exe = true
+            linkerOptions.addAll(["/link", "/nologo", "/SUBSYSTEM:CONSOLE"])
+        }
+        task compileLauncher(dependsOn: [compileWinLauncher, compileIconSwap])
+    } else {
+        task compileLauncher(type: CCTask, group: "Build") {
+            description = "Compiles native sources for the application co-bundle launcher"
+            if (IS_MAC) {
+                matches = ".*\\.m"
+                output(file("$buildDir/classes/main/com/sun/javafx/tools/resource/mac"))
+                params.addAll(CC_PARAMS);
+                source file("src/main/native/launcher/mac")
+                eachOutputFile = { f ->
+                    return new File(f.getParent(), "JavaAppLauncher")
+                }
+            } else {
+                matches = ".*\\.c"
+                output(file("$buildDir/classes/main/com/sun/javafx/tools/resource/linux"))
+                params.addAll(["-DJAVAARCH=\"$OS_ARCH\"", "-I$JDK_HOME/include", "-I$JDK_HOME/include/linux"])
+                linkerOptions.add("-ldl")
+                source file("src/main/native/launcher/linux")
+                eachOutputFile = { f ->
+                    return new File(f.getParent(), "JavaAppLauncher")
+                }
+            }
+        }
+    }
+    assemble.dependsOn compileLauncher;
+
+    // Builds the javafxpackager executable. For everything other than windows,
+    // this is simply moving the existing shell script and ensuring it has proper
+    // permissions. For Windows, this includes compiling the native executable
+    if (IS_WINDOWS){
+        task buildJavaFXPackager(type: CCTask, group: "Build") {
+            description = "Compiles native sources for javafxpackager.exe"
+            matches = "javafxpackager\\.cpp"
+            params.addAll(["/nologo", "/W3", "/EHsc", "/MT", "/GS",
+                    "/DWIN32", "/D_LITTLE_ENDIAN", "/DWIN32_LEAN_AND_MEAN",
+                    "/D_WIN32_WINDOWS=0X0500", "/D_WIN32_WINNT=0X0500",
+                    "/I$JDK_HOME/include", "/I$JDK_HOME/include/win32", "/arch:SSE", "/fp:fast",
+                    "/O2", "-c"])
+            output(file("$buildDir/native"))
+            source file("src/main/native/javafxpackager/win")
+            doLast {
+                mkdir "$buildDir/native"
+                exec({
+                    commandLine("$RC", "/nologo", "/l", "0x409", "/r", "/dJFX_DVERSION=8", "/dJFX_VERSION=8", "/fo$buildDir/native/javafxpackager.res", "src/main/native/javafxpackager/win/javafxpackager.rc");
+                    environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT);
+                });
+            }
+            doLast {
+                mkdir "$buildDir/javafxpackager"
+                exec({
+                    commandLine("$LINK", "/nologo", "/opt:REF", "/incremental:no", "/manifest", "kernel32.lib", "advapi32.lib",
+                            "/out:$buildDir/native/javafxpackager.exe",
+                            "$buildDir/native/javafxpackager.obj", "$buildDir/native/javafxpackager.res")
+                    environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
+                })
+            }
+            doLast {
+                copy {
+                    from file("src/main/native/javafxpackager/win/javafxpackager.manifest")
+                    into file("$buildDir/native")
+                }
+                // TODO, not sure MT.exe is actually being used currently, so for now skipping.
+//                exec({
+//                    commandLine("$MT -nologo -manifest $buildDir/native/javafxpackager.manifest")
+//                    environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
+//                })
+                copy {
+                    from file("$buildDir/native/javafxpackager.exe")
+                    into file("$buildDir/javafxpackager")
+                }
+            }
+        }
+    } else {
+        task buildJavaFXPackager(group: "Build") << {
+            copy {
+                from "src/main/native/javafxpackager/shell"
+                into "$buildDir/javafxpackager"
+                fileMode = 0755
+            }
+        }
+    }
+
+    assemble.dependsOn buildJavaFXPackager
+}
+
 /******************************************************************************
  *                                                                            *
  *                             Top Level Tasks                                *
@@ -1160,6 +1304,7 @@
     group = "Basic"
     description = "Creates the jfxrt.jar"
     archiveName = "build/${COMPILE_TARGET.name}-sdk/rt/lib/ext/jfxrt.jar";
+    includeEmptyDirs = false
     from("modules/base/build/classes/main",
          "modules/base/build/resources/main",
          "modules/graphics/build/classes/main",
@@ -1204,13 +1349,16 @@
 task javadoc(type: Javadoc) {
     group = "Basic"
     description = "Generates the JavaDoc for all the public API"
-    def projectsToDocument = subprojects.findAll({ it != project(":designTime") })
+    executable = JAVADOC
+    def projectsToDocument = [
+            project(":base"), project(":graphics"), project(":controls"),
+            project(":swing"), project(":swt"), project(":fxml")]
     source(projectsToDocument.collect({
         [it.sourceSets.main.java, "$it.buildDir/builder-src"]
     }));
     setDestinationDir(new File(buildDir, 'javadoc'));
     // Might need a classpath
-    classpath = files(subprojects.collect { project ->
+    classpath = files(projectsToDocument.collect { project ->
         project.sourceSets.main.compileClasspath
     });
     exclude("com/**/*", "javafx/scene/ParentDesignInfo*", "Compile*", "javafx/builder/**/*");
@@ -1228,7 +1376,7 @@
         }
     }
 
-    dependsOn(subprojects.collect { project -> project.getTasksByName("classes", true)});
+    dependsOn(projectsToDocument.collect { project -> project.getTasksByName("classes", true)});
 }
 
 // The 'sdk' task will build the rest of the SDK, and depends on the 'jfxrt' task. After
@@ -1251,16 +1399,38 @@
             } else if (COMPILE_TARGET == CompileTarget.WIN) {
                 into("build/${COMPILE_TARGET.name}-sdk/rt/bin");
             } else {
-                into("build/${COMPILE_TARGET.name}-sdk/rt/lib/i386");
+                into("build/${COMPILE_TARGET.name}-sdk/rt/lib/$OS_ARCH");
             }
         }
+
         // Create the javafx.properties file
         final File javafxProperties = file("build/${COMPILE_TARGET.name}-sdk/rt/lib/javafx.properties");
         javafxProperties << "javafx.runtime.version=$RAW_VERSION";
-        // Copy over the javadocs that were generated
+
+        // Copy over the javadocs that were generated. This is done rather than just generating
+        // the docs into the "right place" because for a cross-compile you only need one set of
+        // docs but need to have a copy in each created sdk
         copy {
             from("build/javadoc");
-            into("build/${COMPILE_TARGET.name}-sdk/doc/api");
+            into("build/${COMPILE_TARGET.name}-sdk/docs/api");
+        }
+
+        // Copy over the fxpackager and rename as ant-javafx.jar
+        copy {
+            from "modules/fxpackager/build/libs"
+            into "build/${COMPILE_TARGET.name}-sdk/lib"
+        }
+
+        // Copy over the FXPackager man files
+        copy {
+            from "modules/fxpackager/build/man"
+            into "build/${COMPILE_TARGET.name}-sdk/man"
+        }
+
+        // Copy over the javafxpackager executable
+        copy {
+            from "modules/fxpackager/build/javafxpackager"
+            into "build/${COMPILE_TARGET.name}-sdk/bin"
         }
     }
     dependsOn(jfxrt);
@@ -1333,7 +1503,7 @@
 
 allprojects {
     apply plugin: 'idea'
-    if (project == rootProject) return
+    if (project == rootProject || project.name == "deployment") return
     idea {
         module {
             inheritOutputDirs = true;
--- a/decora-prism-ps/src/com/sun/scenario/effect/impl/prism/ps/PPSRenderer.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/decora-prism-ps/src/com/sun/scenario/effect/impl/prism/ps/PPSRenderer.java	Tue Apr 09 09:33:44 2013 -0700
@@ -271,8 +271,7 @@
     public boolean isImageDataCompatible(final ImageData id) {
         if (getRendererState() == OK) {
             Filterable f = id.getUntransformedImage();
-            return (f instanceof PrDrawable &&
-                    !((PrDrawable) f).isLost());
+            return (f instanceof PrDrawable && !f.isLost());
         }
         return false;
     }
--- a/decora-prism/src/com/sun/scenario/effect/impl/prism/PrDrawable.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/decora-prism/src/com/sun/scenario/effect/impl/prism/PrDrawable.java	Tue Apr 09 09:33:44 2013 -0700
@@ -45,8 +45,6 @@
         return 1.0f;
     }
 
-    public abstract boolean isLost();
-
     public abstract Graphics createGraphics();
 
     public void clear() {
--- a/decora-prism/src/com/sun/scenario/effect/impl/prism/PrImage.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/decora-prism/src/com/sun/scenario/effect/impl/prism/PrImage.java	Tue Apr 09 09:33:44 2013 -0700
@@ -75,6 +75,16 @@
         return image.getPixelScale();
     }
 
+    public void lock() {
+    }
+
+    public void unlock() {
+    }
+
+    public boolean isLost() {
+        return false;
+    }
+
     public void flush() {
         throw new UnsupportedOperationException("Not supported yet.");
     }
--- a/decora-prism/src/com/sun/scenario/effect/impl/prism/PrTexture.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/decora-prism/src/com/sun/scenario/effect/impl/prism/PrTexture.java	Tue Apr 09 09:33:44 2013 -0700
@@ -40,6 +40,14 @@
         this.bounds = new Rectangle(tex.getPhysicalWidth(), tex.getPhysicalHeight());
     }
 
+    public void lock() {
+        if (tex != null) tex.lock();
+    }
+
+    public void unlock() {
+        if (tex != null) tex.unlock();
+    }
+
     public Rectangle getNativeBounds() {
         return bounds;
     }
--- a/decora-runtime/src/com/sun/scenario/effect/Filterable.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/decora-runtime/src/com/sun/scenario/effect/Filterable.java	Tue Apr 09 09:33:44 2013 -0700
@@ -33,4 +33,7 @@
     public int getPhysicalHeight();
     public float getPixelScale();
     public void flush();
+    public void lock();
+    public void unlock();
+    public boolean isLost();
 }
--- a/decora-runtime/src/com/sun/scenario/effect/impl/ImagePool.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/decora-runtime/src/com/sun/scenario/effect/impl/ImagePool.java	Tue Apr 09 09:33:44 2013 -0700
@@ -52,7 +52,7 @@
             public Object run() {
                 if (System.getProperty("decora.showstats") != null) {
                     Runtime.getRuntime().addShutdownHook(new Thread() {
-                        public void run() {
+                        @Override public void run() {
                             printStats();
                         }
                     });
@@ -136,6 +136,14 @@
             if (ew >= w && eh >= h) {
                 int diff = (ew-w) * (eh-h);
                 if (chosenEntry == null || diff < mindiff) {
+                    eimg.lock();
+                    if (eimg.isLost()) {
+                        entries.remove();
+                        continue;
+                    }
+                    if (chosenImage != null) {
+                        chosenImage.unlock();
+                    }
                     chosenEntry = entry;
                     chosenImage = eimg;
                     mindiff = diff;
@@ -193,6 +201,7 @@
             } else if (eimg == img) {
                 chosenEntry = entry;
                 chosenImage = eimg;
+                img.unlock();
                 break;
             }
         }
--- a/deploy/packager/src/com/sun/javafx/tools/resource/PackagerResource.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/deploy/packager/src/com/sun/javafx/tools/resource/PackagerResource.java	Tue Apr 09 09:33:44 2013 -0700
@@ -155,7 +155,10 @@
         final File testFile = new File(path);
         return testFile.isAbsolute()
                    ? testFile
-                   : new File(baseDir.getAbsolutePath(), path);
+                   : new File(baseDir == null 
+                                  ? null 
+                                  : baseDir.getAbsolutePath(),
+                              path);
     }
 
     private static final class TraversalOperation {
--- a/generator.gradle	Thu Apr 04 20:11:19 2013 -0700
+++ b/generator.gradle	Tue Apr 09 09:33:44 2013 -0700
@@ -412,38 +412,84 @@
     // Create the deployment code
     copy {
         from "$RTDir/deploy/javafx-deploy/src/js"
-        into "$FXDir/deploy/deploymentToolkit/src/main/js"
+        into "$FXDir/modules/fxpackager/src/main/resources/resources/web-files"
+    }
+
+    copy {
+        from "$RTDir/deploy/lib"
+        into "$FXDir/modules/fxpackager/src/main/resources/resources/web-files"
+        exclude "java-coffee-cup-23x20.png", "splash.gif"
     }
 
     copy {
         from "$RTDir/deploy/javafx-launcher/src"
-        into "$FXDir/deploy/launcher/src/main/java"
+        into "$FXDir/modules/fxpackager/src/main/java"
     }
 
     copy {
         from "$RTDir/deploy/packager/src"
-        into "$FXDir/deploy/packager/src/main/java"
+        into "$FXDir/modules/fxpackager/src/main/java"
         exclude excludeFromSource
+        exclude "**/*antlib.xml",
+                "**/*.control", "**/*.copyright", "**/*.desktop", "**/*.postinst", "**/*.postrm", "**/*.spec",
+                "**/*.scpt", "**/*.icns", "**/*.template", "**/*.plist",
+                "**/*.bmp", "**/*.ico", "**/*.iss", "**/*.wxs"
     }
 
     copy {
         from "$RTDir/deploy/packager/src", "$RTDir/deploy/packager/scripts"
-        into "$FXDir/deploy/packager/src/main/resources"
+        into "$FXDir/modules/fxpackager/src/main/resources"
         include includeInResources
-        include "**/*antlib.xml"
+        include "**/*antlib.xml",
+                "**/*.control", "**/*.copyright", "**/*.desktop", "**/*.postinst", "**/*.postrm", "**/*.spec",
+                "**/*.scpt", "**/*.icns", "**/*.template", "**/*.plist",
+                "**/*.bmp", "**/*.ico", "**/*.iss", "**/*.wxs"
         exclude excludeFromResources
     }
 
-    ["linux", "macosx", "windows"].each { dir ->
-        copy {
-            from "$RTDir/deploy/packager/native/$dir"
-            into "$FXDir/deploy/packager/native/src/main/$dir"
-        }
+    copy {
+        from "$RTDir/deploy/packager/native/linux"
+        into "$FXDir/modules/fxpackager/src/main/native/launcher/linux"
+    }
+
+    copy {
+        from "$RTDir/deploy/packager/native/macosx"
+        into "$FXDir/modules/fxpackager/src/main/native/launcher/mac"
+    }
+
+    copy {
+        from "$RTDir/deploy/packager/native/windows"
+        into "$FXDir/modules/fxpackager/src/main/native/launcher/win"
+        rename "iconswap.cpp", "IconSwap.cpp"
+        include "WinLauncher.cpp", "iconswap.cpp"
+    }
+
+    copy {
+        from "$RTDir/deploy/packager/scripts"
+        into "$FXDir/modules/fxpackager/src/main/native/javafxpackager/shell"
+    }
+
+    copy {
+        from "$RTDir/deploy/packager/winlauncher"
+        into "$FXDir/modules/fxpackager/src/main/native/javafxpackager/win"
+        include "javafxpackager.manifest", "javafxpackager.rc", "main.cpp"
+        rename "main.cpp", "javafxpackager.cpp"
     }
 
     copy {
         from "$RTDir/deploy/packager/test"
-        into "$FXDir/deploy/packager/test/main/java"
+        into "$FXDir/modules/fxpackager/test/main/java"
+    }
+
+    copy {
+        from "$RTDir/deploy/man"
+        into "$FXDir/modules/fxpackager/src/main/man"
+        exclude "build.xml", "**/ja/**"
+    }
+
+    copy {
+        from "$RTDir/deploy/man/ja"
+        into "$FXDir/modules/fxpackager/src/main/man/ja_JP.UTF-8"
     }
 
     // Find every empty directory and nuke it
--- a/glass/build-closed.xml	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/build-closed.xml	Tue Apr 09 09:33:44 2013 -0700
@@ -61,6 +61,14 @@
       <antcall target="copy-sdk-binaries-linux-lens"/>
     </target>
 
+    <target name="copy-sdk-binaries-android" if="isAndroid">
+      <copy todir="${jfx.sdk.desktop.dir}" flatten="true">
+        <fileset dir="${basedir}">
+          <include name="glass-lib-lens/libs/${cross.platform.arch}/*.so"/>
+        </fileset>
+      </copy>
+    </target>
+
     <target name="copy-sdk-binaries" depends="glass-dist">
       <copy todir="${jfx.sdk.desktop.dir}" flatten="true">
         <fileset refid="glass.libraries.to.be.copied"/>
@@ -68,6 +76,7 @@
       <antcall target="copy-sdk-binaries-linux"/>
       <antcall target="copy-sdk-binaries-macosx"/>
       <antcall target="copy-sdk-binaries-ios"/>
+      <antcall target="copy-sdk-binaries-android"/>
       <antcall target="copy-sdk-binaries-windows"/>
     </target>
 
--- a/glass/build-common.xml	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/build-common.xml	Tue Apr 09 09:33:44 2013 -0700
@@ -24,6 +24,12 @@
       </ant>
     </target>
 
+    <target name="build-android" if="isAndroid">
+      <ant antfile="glass-lib-lens/build-android.xml" target="jar" inheritAll="false">
+        <propertyset id="jfx.build.ant.properties"/>
+      </ant>
+    </target>
+
     <target name="build-linux-gtk" unless="cross.glass.dontBuildGlassGTK">
       <ant antfile="glass-lib-gtk/build.xml" target="default"
            inheritAll="true" useNativeBasedir="true">
@@ -68,6 +74,7 @@
       <antcall target="build-linux"/>
       <antcall target="build-macosx"/>
       <antcall target="build-ios"/>
+      <antcall target="build-android"/>
       <antcall target="build-windows"/>
     </target>
     
@@ -115,6 +122,10 @@
         <propertyset id="jfx.build.ant.properties"/>
       </ant>
     </target>
+
+    <target name="clean-android" if="isAndroid">
+   <ant antfile="glass-lib-lens/build-android.xml" target="clean" inheritAll="false"/>
+    </target>
     
     <target name="clean">
       <delete dir="${basedir}/dist"/>
@@ -125,6 +136,7 @@
       </ant>
       <antcall target="clean-linux"/>
       <antcall target="clean-macosx"/>
+      <antcall target="clean-android"/>
       <antcall target="clean-ios"/>
       <antcall target="clean-windows"/>
     </target>
--- a/glass/glass-lib-gtk/src/GlassCommonDialogs.cpp	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass-lib-gtk/src/GlassCommonDialogs.cpp	Tue Apr 09 09:33:44 2013 -0700
@@ -32,7 +32,7 @@
 #include <cstring>
 #include <cstdlib>
 
-static GSList* setup_GtkFileFilters(GtkFileChooser*, JNIEnv*, jobjectArray);
+static GSList* setup_GtkFileFilters(GtkFileChooser*, JNIEnv*, jobjectArray, int default_filter_index);
 
 static void free_fname(char* fname, gpointer unused) {
     g_free(fname);
@@ -79,7 +79,7 @@
 
 JNIEXPORT jobject JNICALL Java_com_sun_glass_ui_gtk_GtkCommonDialogs__1showFileChooser
   (JNIEnv *env, jclass clazz, jlong parent, jstring folder, jstring name, jstring title,
-   jint type, jboolean multiple, jobjectArray jFilters) {
+   jint type, jboolean multiple, jobjectArray jFilters, jint default_filter_index) {
 
     jobjectArray jFileNames = NULL;
     char* filename;
@@ -120,7 +120,7 @@
 
     gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(chooser), (JNI_TRUE == multiple));
     gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser), chooser_folder);
-    GSList* filters = setup_GtkFileFilters(GTK_FILE_CHOOSER(chooser), env, jFilters);
+    GSList* filters = setup_GtkFileFilters(GTK_FILE_CHOOSER(chooser), env, jFilters, default_filter_index);
 
     if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_ACCEPT) {
         GSList* fnames_gslist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(chooser));
@@ -129,8 +129,7 @@
 
         if (fnames_list_len > 0) {
             jFileNames = env->NewObjectArray((jsize)fnames_list_len, jStringCls, NULL);
-            int i;
-            for(i = 0; i < fnames_list_len; i++) {
+            for (guint i = 0; i < fnames_list_len; i++) {
                 filename = (char*)g_slist_nth(fnames_gslist, i)->data;
                 LOG1("Add [%s] into returned filenames\n", filename)
                 jfilename = env->NewStringUTF(filename);
@@ -218,7 +217,7 @@
  * @param extFilters ExtensionFilter[]
  * @return
  */
-static GSList* setup_GtkFileFilters(GtkFileChooser* chooser, JNIEnv* env, jobjectArray extFilters) {
+static GSList* setup_GtkFileFilters(GtkFileChooser* chooser, JNIEnv* env, jobjectArray extFilters, int default_filter_index) {
     int i;
     LOG0("Setup filters\n")
     //setup methodIDs
@@ -263,6 +262,10 @@
         }
         LOG0("Filter ready\n")
         gtk_file_chooser_add_filter(chooser, ffilter);
+
+        if (default_filter_index == i) {
+            gtk_file_chooser_set_filter(chooser, ffilter);
+        }
         
         filter_list = g_slist_append(filter_list, ffilter);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glass/glass-lib-lens/Android.mk	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,46 @@
+#
+ # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ #
+ # This code is free software; you can redistribute it and/or modify it
+ # under the terms of the GNU General Public License version 2 only, as
+ # published by the Free Software Foundation.  Oracle designates this
+ # particular file as subject to the "Classpath" exception as provided
+ # by Oracle in the LICENSE file that accompanied this code.
+ #
+ # This code is distributed in the hope that it will be useful, but WITHOUT
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ # version 2 for more details (a copy is included in the LICENSE file that
+ # accompanied this code).
+ #
+ # You should have received a copy of the GNU General Public License version
+ # 2 along with this work; if not, write to the Free Software Foundation,
+ # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ #
+ # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ # or visit www.oracle.com if you need additional information or have any
+ # questions.
+ #
+LOCAL_PATH := $(call my-dir)/src
+include $(CLEAR_VARS)
+LOCAL_MODULE := glass-lens-eglfb
+PREFIX := $(LOCAL_PATH)/
+LENS_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.c)
+
+LOCAL_SRC_FILES := LensApplication.c LensCursor.c LensCursorImages.c \
+LensInputEvents.c LensLogger.c LensPixels.c LensRobot.c LensScreen.c LensView.c LensWindow.c
+LOCAL_SRC_FILES += android/Main.c
+LOCAL_SRC_FILES += wm/LensWindowManager.c wm/robot.c
+LOCAL_SRC_FILES += wm/screen/androidScreen.c
+LOCAL_SRC_FILES += cursor/nullCursor/nullCursor.c
+LOCAL_SRC_FILES += input/android/androidInput.c
+
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/android $(LOCAL_PATH)/../build/android/include
+LOCAL_STATIC_LIBRARIES := android_native_app_glue
+LOCAL_LDLIBS += -landroid -llog
+LOCAL_CFLAGS += -DANDROID_NDK -DDEBUG -std=c99 
+
+include $(BUILD_SHARED_LIBRARY)
+$(call import-module,android/native_app_glue)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glass/glass-lib-lens/build-android.xml	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project name="glass-lib-lens-android" default="jar" basedir=".">
+  <description>Builds, tests, and runs the project glass.</description>
+
+  <import file="../../../build-defs.xml"/>
+
+  <property name="build.dir" value="./build${cross.name.suffix}"/>
+  <property name="jheaders.dir" value="${build.dir}/include"/>
+  <property name="dist.dir" value="./dist${cross.name.suffix}"/>
+  <property name="native.lib.file" value="libglass-lens-eglfb.so"/>
+  <property name="glass.classpath" value="../glass/build/classes"/>
+
+  <target name="jheaders" unless="uptodate">
+   <mkdir dir="${jheaders.dir}" />
+        <javah destdir="${jheaders.dir}" classpath="${glass.classpath}" force="yes">
+            <class name="com.sun.glass.events.DndEvent"/>
+            <class name="com.sun.glass.events.KeyEvent"/>
+            <class name="com.sun.glass.events.MouseEvent"/>
+            <class name="com.sun.glass.events.TouchEvent"/>
+            <class name="com.sun.glass.events.ViewEvent"/>
+            <class name="com.sun.glass.events.WindowEvent"/>
+            <class name="com.sun.glass.ui.Application"/>
+            <class name="com.sun.glass.ui.Cursor"/>
+            <class name="com.sun.glass.ui.Menu"/>
+            <class name="com.sun.glass.ui.MenuBar"/>
+            <class name="com.sun.glass.ui.MenuItem"/>
+            <class name="com.sun.glass.ui.Pixels"/>
+            <class name="com.sun.glass.ui.Robot"/>
+            <class name="com.sun.glass.ui.Screen"/>
+            <class name="com.sun.glass.ui.Size"/>
+            <class name="com.sun.glass.ui.Timer"/>
+            <class name="com.sun.glass.ui.View"/>
+            <class name="com.sun.glass.ui.View$Capability"/>
+            <class name="com.sun.glass.ui.Window"/>
+            <class name="com.sun.glass.ui.Window$Level"/>
+            <class name="com.sun.glass.ui.lens.LensApplication"/>
+            <class name="com.sun.glass.ui.lens.LensCursor"/>
+            <class name="com.sun.glass.ui.lens.LensPixels"/>
+            <class name="com.sun.glass.ui.lens.LensView"/>
+            <class name="com.sun.glass.ui.lens.LensWindow"/>
+            <class name="com.sun.glass.ui.lens.LensRobot"/>
+            <class name="com.sun.glass.ui.lens.LensClipboardDelegate"/>
+        </javah>
+    </target>
+
+    <target name="check-native">
+     <uptodate property="uptodate" targetfile="libs/armeabi/${native.lib.file}" >
+      <srcfiles dir="src" includes="**/*.c"/>
+      <srcfiles dir="src" includes="**/*.h"/>
+      <srcfiles dir="${glass.classpath}" includes="**/*.class"/>
+     </uptodate>
+  </target>
+
+    <target name="compile-native-eglfb" unless="uptodate">
+        <exec executable="${ndk.build.cmd}" dir="${basedir}" failonerror="true">
+     <arg line="APP_BUILD_SCRIPT=Android.mk NDK_PROJECT_PATH=. TARGET_PLATFORM=${android.ndk.target}"/>
+        </exec>
+    </target>
+
+    <target name="jar" depends="check-native, jheaders, compile-native-eglfb"/>
+
+    <target name="clean">
+   <delete dir="libs"/>
+   <delete dir="obj"/>
+        <delete dir="${dist.dir}"/>
+        <delete dir="${build.dir}"/>
+    </target>
+
+</project>
--- a/glass/glass-lib-lens/src/LensCommon.h	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass-lib-lens/src/LensCommon.h	Tue Apr 09 09:33:44 2013 -0700
@@ -26,6 +26,9 @@
 #ifndef LENS_COMMON_H
 #define LENS_COMMON_H
 
+#ifdef ANDROID_NDK
+#include <stdio.h>
+#endif
 #include "stdlib.h"
 #include "string.h"
 #include <unistd.h>
@@ -1469,10 +1472,6 @@
  * @param level the logging level (e.g. LOG_WARNING)
  * @param ... a format string and parameters in printf format
  */
-#define GLASS_LOG(level,...) \
-    GLASS_IF_LOG(level) \
-    glass_logf(level, __func__, __FILE__, __LINE__, __VA_ARGS__)
-
 /** Logging levels, with same meanings as in java.util.logging.Level */
 #define GLASS_LOG_LEVEL_SEVERE  1000
 #define GLASS_LOG_LEVEL_WARNING 900
@@ -1482,6 +1481,20 @@
 #define GLASS_LOG_LEVEL_FINER   400
 #define GLASS_LOG_LEVEL_FINEST  300
 
+#ifdef ANDROID_NDK
+// Can't use java logger in jvm8 on Android. Remove when this issue is fixed.
+#include <android/log.h>
+#define TAG "GLASS"
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, __VA_ARGS__))
+#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, __VA_ARGS__))
+#define GLASS_LOG(level,...) \
+        LOGI(TAG, __VA_ARGS__)
+#else
+#define GLASS_LOG(level,...) \
+    GLASS_IF_LOG(level) \
+    glass_logf(level, __func__, __FILE__, __LINE__, __VA_ARGS__)
+
 #define GLASS_IF_LOG_SEVERE  GLASS_IF_LOG(GLASS_LOG_LEVEL_SEVERE)
 #define GLASS_IF_LOG_WARNING GLASS_IF_LOG(GLASS_LOG_LEVEL_WARNING)
 #define GLASS_IF_LOG_INFO    GLASS_IF_LOG(GLASS_LOG_LEVEL_INFO)
@@ -1489,6 +1502,7 @@
 #define GLASS_IF_LOG_FINE    GLASS_IF_LOG(GLASS_LOG_LEVEL_FINE)
 #define GLASS_IF_LOG_FINER   GLASS_IF_LOG(GLASS_LOG_LEVEL_FINER)
 #define GLASS_IF_LOG_FINEST  GLASS_IF_LOG(GLASS_LOG_LEVEL_FINEST)
+#endif
 
 #ifdef NO_LOGGING
 #define GLASS_LOG_SEVERE(...)  (void)0, ##__VA_ARGS__
--- a/glass/glass-lib-lens/src/LensInputEvents.c	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass-lib-lens/src/LensInputEvents.c	Tue Apr 09 09:33:44 2013 -0700
@@ -230,7 +230,11 @@
                 shiftDown++;
                 GLASS_LOG_FINER("SHIFT was pressed shiftDown = %d", shiftDown);
             } else {
-                shiftDown --;
+       #ifdef ANDROID_NDK  
+                shiftDown = 0;
+       #else
+                shiftDown--;
+       #endif
                 GLASS_LOG_FINER("SHIFT was released shiftDown = %d", shiftDown);
             }
             //update mask
@@ -249,7 +253,11 @@
                 ctrlDown++;
                 GLASS_LOG_FINER("CTRL was pressed");
             } else {
+       #ifdef ANDROID_NDK
+                ctrlDown = 0;
+       #else
                 ctrlDown--;
+       #endif
                 GLASS_LOG_FINER("CTRL was released");
             }
             //update mask
@@ -267,8 +275,12 @@
             if (isPressed) {
                 altDown++;
                 GLASS_LOG_FINER("ALT was pressed");
-            } else {
-                altDown --;
+            } else {                
+       #ifdef ANDROID_NDK
+                altDown = 0;
+       #else
+                altDown--;
+       #endif
                 GLASS_LOG_FINER("ALT was released");
             }
             //update mask
@@ -287,7 +299,11 @@
                 metaDown++;
                 GLASS_LOG_FINER("META was pressed");
             } else {
-                metaDown --;
+       #ifdef ANDROID_NDK
+                metaDown = 0;
+       #else
+                metaDown--;
+       #endif
                 GLASS_LOG_FINER("META was released");
             }
             //update mask
--- a/glass/glass-lib-lens/src/LensLogger.c	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass-lib-lens/src/LensLogger.c	Tue Apr 09 09:33:44 2013 -0700
@@ -26,7 +26,10 @@
 #include "LensCommon.h"
 
 #include <assert.h>
+#ifndef ANDROID_NDK
+//Backtrace is not available on Android. Need to find workaround.
 #include <execinfo.h>
+#endif
 #include <sys/types.h>
 #include <linux/unistd.h>
 #include <sys/syscall.h>
@@ -282,6 +285,11 @@
     }
 }
 
+#ifdef ANDROID_NDK
+void glass_backtrace() {
+    fprintf(stderr, "backtrace not supported on Android!");
+}
+#else
 void glass_backtrace() {
     JNIEnv *env;
     int i;
@@ -387,4 +395,4 @@
     }
     fflush(stderr);
 }
-
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glass/glass-lib-lens/src/android/Main.c	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#ifdef ANDROID_NDK
+
+#include <jni.h>
+#include <android/log.h>
+#include <string.h>
+#include <assert.h>
+#include "LensCommon.h"
+#include "Main.h"
+
+/*
+ * This is the activity context we got from NativeActivity.
+ * Stored for later use in glass.
+ */
+DvkContext context;
+
+ANativeWindow *getAndroidNativeWindow() {
+   assert(context);
+   if (context->app->activityState == APP_CMD_PAUSE ||
+      context->app->activityState == APP_CMD_STOP) {
+      return NULL;
+   }
+   return context->app->window;
+}
+
+DvkContext getDvkContext() {
+   return context;
+}
+
+const char *getExternalDataPath() {
+   return context->app->activity->externalDataPath;
+}
+
+void android_main(struct android_app *app) {
+
+   app_dummy();
+
+   context = (DvkContext)malloc(sizeof(struct _DvkContext));
+   assert(context);
+    memset(context, 0, sizeof(struct _DvkContext));
+
+    //save reference to android activity
+    context->app = app;
+
+    dvkEventLoop(context); //block until application ends
+
+    free(context);
+}
+
+#endif /* ANDROID_NDK */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glass/glass-lib-lens/src/android/Main.h	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef MAIN_H_
+#define MAIN_H_
+
+#include <android_native_app_glue.h>
+
+#define TRUE  1
+#define FALSE 0;
+
+#define CHECK_JNI_EXCEPTION(env) \
+        if ((*env)->ExceptionCheck(env)) {\
+            return;\
+        }
+
+#define CHECK_JNI_EXCEPTION_RET(env, ret) \
+        if ((*env)->ExceptionCheck(env)) {\
+                return ret;\
+        }
+
+typedef uint8_t boolean;
+
+struct _DvkContext {
+   struct android_app *app;
+};
+
+typedef struct _DvkContext *DvkContext;
+
+ANativeWindow *getAndroidNativeWindow();
+
+DvkContext getDvkContext();
+
+const char *getExternalDataPath();
+
+void dvkEventLoop(DvkContext context);
+
+//jni references
+extern jmethodID jRunnableRun;
+
+#endif /* MAIN_H_ */
--- a/glass/glass-lib-lens/src/cursor/fbCursor/fbDispman.c	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass-lib-lens/src/cursor/fbCursor/fbDispman.c	Tue Apr 09 09:33:44 2013 -0700
@@ -66,7 +66,6 @@
 
 
 static DispManCursor cursor;
-static DISPMANX_RESOURCE_HANDLE_T screenResource = 0;
 
 static void *fbCursorUpdater(void *data);
 static void fbDispmanAddDispmanxElement(void);
@@ -341,17 +340,24 @@
     VC_IMAGE_TRANSFORM_T transform = 0;
     DISPMANX_RESOURCE_HANDLE_T resource = 0;
     DISPMANX_DISPLAY_HANDLE_T display = 0;
+    DISPMANX_RESOURCE_HANDLE_T screenResource = 0;
     uint32_t imagePtr;
     int rc;
 
     GLASS_LOG_FINE("Capture %i,%i+%ix%i", x, y, width, height);
 
+    if (width < 1 || height < 1) {
+        GLASS_LOG_SEVERE("Failed. width/height values must be at least = 1");
+        return JNI_FALSE;
+    }
+
     GLASS_LOG_FINE("open(%s, O_RDONLY)", FB_DEVICE);
     fbFileHandle = open(FB_DEVICE, O_RDONLY);
     if (fbFileHandle < 0) {
         GLASS_LOG_SEVERE("Cannot open framebuffer");
         return JNI_FALSE;
     }
+
     GLASS_LOG_FINE("ioctl(%s, FBIOGET_VSCREENINFO)", FB_DEVICE);
     if (ioctl(fbFileHandle, FBIOGET_VSCREENINFO, &screenInfo)) {
         GLASS_LOG_SEVERE("Cannot get screen info");
@@ -364,10 +370,11 @@
                    screenInfo.xoffset, screenInfo.yoffset);
     GLASS_LOG_FINE("close(%s)", FB_DEVICE);
     close(fbFileHandle);
+
     VC_RECT_T pixelRect = { 0, 0, screenInfo.xres, screenInfo.yres };
 
-    pixelBuffer = (unsigned int *) malloc(
-                      screenInfo.xres * screenInfo.yres * 4);
+    int pixelBufferLength = screenInfo.xres * screenInfo.yres * 4;
+    pixelBuffer = (unsigned int *) malloc(pixelBufferLength);
     pixelBufferPtr = (unsigned char *) pixelBuffer;
 
     if (pixelBuffer == NULL) {
@@ -384,16 +391,16 @@
         free(pixelBuffer);
         return JNI_FALSE;
     }
+
     // create the resource for the snapshot
+    screenResource = vc_dispmanx_resource_create(VC_IMAGE_ARGB8888, screenInfo.xres, screenInfo.yres, &imagePtr);
     if (!screenResource) {
-        screenResource = vc_dispmanx_resource_create(VC_IMAGE_ARGB8888, screenInfo.xres, screenInfo.yres, &imagePtr);
-        if (!screenResource) {
-            fprintf(stderr, "fbRobotScreenCapture: Cannot create resource\n");
-            vc_dispmanx_display_close(display);
-            free(pixelBuffer);
-            return JNI_FALSE;
-        }
+        fprintf(stderr, "fbRobotScreenCapture: Cannot create resource\n");
+        vc_dispmanx_display_close(display);
+        free(pixelBuffer);
+        return JNI_FALSE;
     }
+
     rc = vc_dispmanx_snapshot(display, screenResource, transform);
     if (rc) {
         fprintf(stderr, "fbRobotScreenCapture: snapshot failed\n");
@@ -410,11 +417,14 @@
         return JNI_FALSE;
     }
 
-    if (width < 1 || height < 1) {
-        GLASS_LOG_SEVERE("Failed. width/height values must be at least = 1");
+    rc = vc_dispmanx_resource_delete(screenResource);
+    if (rc) {
+        fprintf(stderr, "fbRobotScreenCapture: failed to free buffer %d\n", rc);
+        vc_dispmanx_display_close(display);
         free(pixelBuffer);
         return JNI_FALSE;
     }
+    screenResource = 0;
 
     if (x < 0) {
         pixelBuffer += -x;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glass/glass-lib-lens/src/input/android/androidInput.c	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#ifdef ANDROID_NDK
+
+#include "android/Main.h"
+#include "androidInput.h"
+#include "input/LensInput.h"
+#include "com_sun_glass_events_TouchEvent.h"
+#include "com_sun_glass_events_MouseEvent.h"
+#include "com_sun_glass_events_KeyEvent.h"
+#include "com_sun_glass_ui_lens_LensApplication.h"
+
+#define round(x) ((x)>=0?(int)((x)+0.5):(int)((x)-0.5))
+
+#define WAIT_FOR_EVENTS -1
+
+struct _TouchPoint {
+   int x;
+   int y;
+   int32_t action;
+};
+
+typedef struct _TouchPoint *TouchPoint;
+
+JNIEnv *glass_env;
+
+void handle_cmd(struct android_app* app, int32_t cmd) {
+    switch (cmd) {
+        case APP_CMD_START:
+           GLASS_LOG_FINE("APP_CMD_START");
+           break;
+        case APP_CMD_STOP:
+           GLASS_LOG_FINE("APP_CMD_STOP");
+            break;
+        case APP_CMD_PAUSE:
+           GLASS_LOG_FINE("APP_CMD_PAUSE");
+            break;
+        case APP_CMD_SAVE_STATE:
+           GLASS_LOG_FINE("APP_CMD_SAVE_STATE");
+            break;
+        case APP_CMD_INIT_WINDOW:
+           GLASS_LOG_FINE("APP_CMD_INIT_WINDOW");
+            break;
+        case APP_CMD_TERM_WINDOW:
+           GLASS_LOG_FINE("APP_CMD_TERM_WINDOW");
+            break;
+        case APP_CMD_GAINED_FOCUS:
+           GLASS_LOG_FINE("APP_CMD_GAINED_FOCUS");
+            break;
+        case APP_CMD_LOST_FOCUS:
+            GLASS_LOG_FINE("APP_CMD_LOST_FOCUS");
+            break;
+    }
+}
+
+jboolean lens_input_initialize(JNIEnv *env){
+   uint32_t flags = 0;
+   flags |= 1 << com_sun_glass_ui_lens_LensApplication_DEVICE_MULTITOUCH;
+   glass_application_notifyDeviceEvent(env, flags, TRUE);
+    return JNI_TRUE;
+}
+
+void lens_input_shutdown() {
+   if (glass_env) {
+       JavaVM *glass_vm = glass_application_GetVM();
+       (*glass_vm)->DetachCurrentThread(glass_vm);
+   }
+}
+
+int32_t translateToLinuxKeyCode(int32_t androidKeyCode) {
+    for (int i = 0 ; i < sizeof(keyMap) ; ++i) {
+        if (keyMap[i].androidKC == androidKeyCode) {
+            return keyMap[i].linuxKC;
+        }
+    }
+    return KEY_RESERVED;
+}
+
+TouchPoint getTouchPoint(TouchPoint tp, AInputEvent *event, int pindex) {
+   tp->x = round(AMotionEvent_getX(event, pindex));
+   tp->y = round(AMotionEvent_getY(event, pindex));
+   tp->action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK;
+   GLASS_LOG_FINE("TouchPoint [action:%i x:%i y:%i]", tp->action, tp->x, tp->y);
+   return tp;
+}
+
+JNIEnv *getJNIEnv() {
+   if (!glass_env) {
+       JavaVM *glass_vm = glass_application_GetVM();
+       if (glass_vm == NULL) {
+           return NULL;
+       }
+       (*glass_vm)->AttachCurrentThread(glass_vm, (void **) &glass_env, NULL);
+       if (glass_env == NULL) {
+           GLASS_LOG_WARNING("Cannot attach native event thread to VM!");
+           return NULL;
+       }
+       GLASS_LOG_FINE("Native event thread attached to VM.");
+   }
+   return glass_env;
+}
+
+void handle_motion_event(AInputEvent* event) {
+
+   JNIEnv *env;
+   if (NULL == (env = getJNIEnv())) {
+       GLASS_LOG_WARNING("Ignoring event");
+       return;
+   }
+
+   int32_t pointerIndex = 0;
+   size_t  pcount = 1;
+   int32_t deviceID = AInputEvent_getDeviceId(event);
+   int32_t source = AInputEvent_getSource(event);
+   int32_t action = AMotionEvent_getAction(event);
+   int32_t actionCode = action & AMOTION_EVENT_ACTION_MASK;
+    TouchPoint tp = malloc(sizeof(struct _TouchPoint));
+
+   switch(actionCode) {
+       case AMOTION_EVENT_ACTION_CANCEL:
+           GLASS_LOG_FINE("Motion Event: Cancel");
+           break;
+       case AMOTION_EVENT_ACTION_DOWN:
+           tp = getTouchPoint(tp, event, 0);
+           lens_wm_notifyTouchEvent(env, com_sun_glass_events_TouchEvent_TOUCH_PRESSED, 0, tp->x, tp->y);
+           lens_wm_notifyButtonEvent(env, JNI_TRUE, com_sun_glass_events_MouseEvent_BUTTON_LEFT, tp->x, tp->y);
+           break;
+       case AMOTION_EVENT_ACTION_MOVE:
+           tp = getTouchPoint(tp, event, 0);
+           lens_wm_notifyMotionEvent(env, tp->x, tp->y, TRUE, 0);
+           break;
+       case AMOTION_EVENT_ACTION_UP:
+           tp = getTouchPoint(tp, event, 0);
+           lens_wm_notifyTouchEvent(env, com_sun_glass_events_TouchEvent_TOUCH_RELEASED, 0, tp->x, tp->y);
+           lens_wm_notifyButtonEvent(env, JNI_FALSE, com_sun_glass_events_MouseEvent_BUTTON_LEFT, tp->x, tp->y);
+           break;
+       case AMOTION_EVENT_ACTION_POINTER_DOWN:
+       case AMOTION_EVENT_ACTION_POINTER_UP:
+           pointerIndex = action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK;
+           pcount = AMotionEvent_getPointerCount(event);
+           for(int i = 0; i < pcount; i++) {
+               tp = getTouchPoint(tp, event, i);
+               if (i == pointerIndex) {
+                   /* TODOEnable when there is a support for multitouch in lens.
+                   lens_wm_notifyTouchEvent(env,
+                           actionCode == AMOTION_EVENT_ACTION_POINTER_DOWN ?
+                           com_sun_glass_events_TouchEvent_TOUCH_PRESSED :
+                           com_sun_glass_events_TouchEvent_TOUCH_RELEASED,
+                           i, tp->x, tp->y);
+                   */
+               } else {
+                   /*
+                   lens_wm_notifyTouchEvent(env, com_sun_glass_events_TouchEvent_TOUCH_STILL, i, tp->x, tp->y);
+                   */
+               }
+           }//for
+           break;
+   }//switch
+
+   free(tp);
+}
+
+void handle_key_event(AInputEvent *event) {
+
+   JNIEnv *env;
+   if (NULL == (env = getJNIEnv())) {
+       GLASS_LOG_WARNING("Ignoring event");
+       return;
+   }
+
+    int32_t deviceID = AInputEvent_getDeviceId(event);
+   int32_t source = AInputEvent_getSource(event);
+   int32_t action = AKeyEvent_getAction(event);
+   int32_t jfxEventType;
+   int32_t jfxKeyCode;
+   int32_t keyCode;
+   int32_t kcount = 1;
+   jboolean isRepeatEvent = JNI_FALSE;
+
+   NativeWindow window = glass_window_getFocusedWindow();
+
+   if (window == NULL) {
+       GLASS_LOG_FINE("Skipping event, no focused window");
+       return;
+   }
+
+   switch (action) {
+       case AKEY_EVENT_ACTION_DOWN:
+           jfxEventType = com_sun_glass_events_KeyEvent_PRESS;
+           keyCode = AKeyEvent_getKeyCode(event);
+           GLASS_LOG_FINE("AKEY_EVENT_ACTION_DOWN:[%i]", keyCode);
+           jfxKeyCode = glass_inputEvents_getJavaKeycodeFromPlatformKeyCode(
+                            translateToLinuxKeyCode(keyCode));
+           break;
+
+       case AKEY_EVENT_ACTION_UP:
+           jfxEventType = com_sun_glass_events_KeyEvent_RELEASE;
+           keyCode = AKeyEvent_getKeyCode(event);
+           GLASS_LOG_FINE("AKEY_EVENT_ACTION_UP:[%i]", keyCode);
+           jfxKeyCode = glass_inputEvents_getJavaKeycodeFromPlatformKeyCode(
+                            translateToLinuxKeyCode(keyCode));
+           break;
+
+       case AKEY_EVENT_ACTION_MULTIPLE:
+           GLASS_LOG_FINE("AKEY_EVENT_ACTION_MULTIPLE:");
+           jfxEventType = com_sun_glass_events_KeyEvent_PRESS;
+           isRepeatEvent = JNI_TRUE;
+           keyCode = AKeyEvent_getKeyCode(event);
+           jfxKeyCode = glass_inputEvents_getJavaKeycodeFromPlatformKeyCode(
+                           translateToLinuxKeyCode(keyCode));
+           kcount = AKeyEvent_getRepeatCount(event);
+           break;
+
+       default:
+           GLASS_LOG_FINE("Skipping event, unsupported event[%d]", action);
+           break;
+   }
+
+   GLASS_LOG_FINEST("Notifying key event on windows %d[%p] - "
+                            "event type %d, key code %d, is repeat?%s",
+                            window->id, window, jfxEventType, jfxKeyCode,
+                            (isRepeatEvent ? "yes" : "no"));
+
+   if (action != AKEY_EVENT_ACTION_MULTIPLE) {
+       glass_application_notifyKeyEvent(env, window, jfxEventType, jfxKeyCode, isRepeatEvent);
+   }
+}
+
+int32_t handle_input(struct android_app* app, AInputEvent* event) {
+
+   if (AINPUT_EVENT_TYPE_MOTION == AInputEvent_getType(event)) {
+       GLASS_LOG_FINE("Got motion input event.");
+       handle_motion_event(event);
+
+   } else if (AINPUT_EVENT_TYPE_KEY == AInputEvent_getType(event)) {
+       GLASS_LOG_FINE("Got key input event.");
+       handle_key_event(event);
+
+   } else {
+       GLASS_LOG_WARNING("Unknown event type!");
+   }
+
+    return 0;
+}
+
+void dvkEventLoop(DvkContext context) {
+   int ident;
+   int events;
+   struct android_poll_source* source;
+
+   context->app->onAppCmd = handle_cmd;
+   context->app->onInputEvent = handle_input;
+
+   while(1) {
+       GLASS_LOG_FINE( "Native event loop start.");
+
+       while((ident=ALooper_pollAll(WAIT_FOR_EVENTS, NULL, &events,
+               (void**)&source)) >= 0) {
+
+           // Process this event.
+           if (source != NULL) {
+               source->process(context->app, source);
+           }
+
+           // Check if we are exiting.
+           if (context->app->destroyRequested != 0) {
+               GLASS_LOG_FINE("Native event loop end.");
+               return;
+           }
+       }
+   }//event loop
+
+void showIme(int32_t flags) {
+   DvkContext context = getDvkContext();
+   ANativeActivity_showSoftInput(context->app->activity, flags);
+}
+
+void hideIme(int32_t flags) {
+   DvkContext context = getDvkContext();
+   ANativeActivity_hideSoftInput(context->app->activity, flags);
+}
+
+}
+
+#endif /* ANDROID_NDK */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glass/glass-lib-lens/src/input/android/androidInput.h	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef ANDROIDINPUT_H_
+#define ANDROIDINPUT_H_
+
+#include <android/keycodes.h>
+#include <linux/input.h>
+
+typedef struct {
+   int32_t androidKC;
+   int32_t linuxKC;
+} AndroidLinuxKC;
+
+static AndroidLinuxKC keyMap[] = {
+       {AKEYCODE_UNKNOWN, KEY_RESERVED},
+       {AKEYCODE_0, KEY_0},
+       {AKEYCODE_1, KEY_1},
+       {AKEYCODE_2, KEY_2},
+       {AKEYCODE_3, KEY_3},
+       {AKEYCODE_4, KEY_4},
+       {AKEYCODE_5, KEY_5},
+       {AKEYCODE_6, KEY_6},
+       {AKEYCODE_7, KEY_7},
+       {AKEYCODE_8, KEY_8},
+       {AKEYCODE_9, KEY_9},
+       {AKEYCODE_MINUS, KEY_MINUS},
+       {AKEYCODE_EQUALS, KEY_EQUAL},
+       {AKEYCODE_TAB, KEY_TAB},
+       {AKEYCODE_Q, KEY_Q},
+       {AKEYCODE_W, KEY_W},
+       {AKEYCODE_E, KEY_E},
+       {AKEYCODE_R, KEY_R},
+       {AKEYCODE_T, KEY_T},
+       {AKEYCODE_Y, KEY_Y},
+       {AKEYCODE_U, KEY_U},
+       {AKEYCODE_I, KEY_I},
+       {AKEYCODE_O, KEY_O},
+       {AKEYCODE_P, KEY_P},
+       {AKEYCODE_LEFT_BRACKET, KEY_LEFTBRACE},
+       {AKEYCODE_RIGHT_BRACKET, KEY_RIGHTBRACE},
+       {AKEYCODE_ENTER, KEY_ENTER},
+       //{AKEYCODE_CTRL_LEFT, KEY_LEFTCTRL},
+       //{AKEYCODE_CTRL_RIGHT, KEY_RIGHTCTRL},
+       {AKEYCODE_A, KEY_A},
+       {AKEYCODE_S, KEY_S},
+       {AKEYCODE_D, KEY_D},
+       {AKEYCODE_F, KEY_F},
+       {AKEYCODE_G, KEY_G},
+       {AKEYCODE_H, KEY_H},
+       {AKEYCODE_J, KEY_J},
+       {AKEYCODE_K, KEY_K},
+       {AKEYCODE_L, KEY_L},
+       {AKEYCODE_SEMICOLON, KEY_SEMICOLON},
+       {AKEYCODE_GRAVE, KEY_GRAVE},
+       {AKEYCODE_SHIFT_LEFT, KEY_LEFTSHIFT},
+       {AKEYCODE_BACKSLASH, KEY_BACKSLASH},
+       {AKEYCODE_Z, KEY_Z},
+       {AKEYCODE_X, KEY_X},
+       {AKEYCODE_C, KEY_C},
+       {AKEYCODE_V, KEY_V},
+       {AKEYCODE_B, KEY_B},
+       {AKEYCODE_N, KEY_N},
+       {AKEYCODE_M, KEY_M},
+       {AKEYCODE_APOSTROPHE, KEY_APOSTROPHE},
+       {AKEYCODE_COMMA, KEY_COMMA},
+       {AKEYCODE_PERIOD, KEY_DOT},
+       {AKEYCODE_SLASH, KEY_SLASH},
+       {AKEYCODE_SHIFT_RIGHT, KEY_RIGHTSHIFT},
+       {AKEYCODE_STAR, KEY_KPASTERISK},
+       {AKEYCODE_ALT_LEFT, KEY_LEFTALT},
+       {AKEYCODE_SPACE, KEY_SPACE},
+       //{AKEYCODE_CAPSLOCK, KEY_CAPSLOCK},
+       //{AKEYCODE_CTRL_RIGHT, KEY_RIGHTCTRL},
+       {AKEYCODE_ALT_RIGHT, KEY_RIGHTALT},
+       {AKEYCODE_HOME, KEY_HOME},
+       {AKEYCODE_DPAD_UP, KEY_UP},
+       {AKEYCODE_PAGE_UP, KEY_PAGEUP},
+       {AKEYCODE_DPAD_LEFT, KEY_LEFT},
+       {AKEYCODE_DPAD_RIGHT, KEY_RIGHT},
+       //{AKEYCODE_END, KEY_END},
+       {AKEYCODE_DPAD_DOWN, KEY_DOWN},
+       {AKEYCODE_PAGE_DOWN, KEY_PAGEDOWN},
+       //{AKEYCODE_INSERT, KEY_INSERT},
+       {AKEYCODE_DEL, KEY_DELETE},
+};
+
+#endif /* ANDROIDINPUT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glass/glass-lib-lens/src/wm/screen/androidScreen.c	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifdef ANDROID_NDK
+
+#include "LensCommon.h"
+#include "input/LensInput.h"
+#include "wm/LensWindowManager.h"
+#include "android/Main.h"
+
+static struct _NativeScreen localScreen;
+static int windowIndex = 1;
+
+NativeScreen lens_screen_initialize(JNIEnv *env) {
+
+   ANativeWindow *androidWindow = getAndroidNativeWindow();
+   int32_t width = ANativeWindow_getWidth(androidWindow);
+    int32_t height = ANativeWindow_getHeight(androidWindow);
+
+    localScreen.width = width;
+    localScreen.height = height;
+    localScreen.visibleWidth = width;
+    localScreen.visibleHeight = height;
+    localScreen.x = 0;
+    localScreen.y = 0;
+    localScreen.depth = 24; //????? Samsung has 16
+
+    // convert pixels/mm to pixels/inch
+    localScreen.resolutionX = 100;
+    localScreen.resolutionY = 100;
+
+    //localScreen.data = malloc(localScreen.width * localScreen.height * sizeof(int));
+
+    return &localScreen;
+}
+
+jboolean glass_application_initialize(JNIEnv *env) {
+    //nothing to do
+    return JNI_TRUE;
+}
+
+jboolean glass_window_setAlpha(JNIEnv *env, NativeWindow window, float alpha) {
+    window->alpha = alpha;
+    lens_wm_repaint(env, window);
+    return JNI_TRUE;
+}
+
+LensResult glass_view_PlatformViewData_create(NativeView view) {
+    view->data = NULL;
+    return LENS_OK;
+}
+
+LensResult glass_view_PlatformViewRelease(JNIEnv *env, NativeView view) {
+    // No data to free
+    return LENS_OK;
+}
+
+LensResult glass_window_PlatformWindowData_create(JNIEnv *env,
+                                                  NativeWindow window) {
+
+    window->id = windowIndex++;
+    window->data = NULL; //no platfrom specific data
+
+    return LENS_OK;
+}
+
+LensResult glass_window_PlatformWindowRelease(JNIEnv *env, NativeWindow window) {
+    // No data to free
+    return LENS_OK;
+}
+
+void *glass_window_getPlatformWindow(JNIEnv *env, NativeWindow window) {
+    return getAndroidNativeWindow();
+}
+
+void lens_platform_shutdown(JNIEnv *env) {
+    lens_input_shutdown();
+}
+
+void glass_screen_clear() {
+    // NOOP
+}
+
+void glass_pixel_attachIntBuffer(JNIEnv *env, jint *src,
+                                 NativeWindow window,
+                                 jint width, jint height, int offset) {
+   GLASS_LOG_FINE("androidScreen: glass_pixel_attachIntBuffer not implemented!");
+}
+
+jboolean glass_screen_capture(jint x,
+                              jint y,
+                              jint width,
+                              jint height,
+                              jint *pixels) {
+   GLASS_LOG_FINE("androidScreen: glass_screen_capture not implemented!");
+}
+
+#endif /* ANDROID_NDK */
--- a/glass/glass-lib-lens/src/wm/screen/fbdevScreen.c	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass-lib-lens/src/wm/screen/fbdevScreen.c	Tue Apr 09 09:33:44 2013 -0700
@@ -345,6 +345,11 @@
         GLASS_LOG_FINE("Capture %i,%i+%ix%i", x, y, width, height);
         jboolean result = JNI_FALSE;
 
+        if (width < 1 || height < 1) {
+            GLASS_LOG_SEVERE("Failed. width/height values must be at least = 1");
+            return JNI_FALSE;
+        }
+
         GLASS_LOG_FINE("open(%s, O_RDONLY)", FB_DEVICE);
         fbFileHandle = open(FB_DEVICE, O_RDONLY);
         if (fbFileHandle < 0) {
@@ -362,8 +367,8 @@
         GLASS_LOG_FINE("close(%s)", FB_DEVICE);
         close(fbFileHandle);
         depth = screenInfo.bits_per_pixel / 8;
-        pixelBuffer = (unsigned char *) malloc(
-                                              screenInfo.xres * screenInfo.yres * depth);
+        int pixelBufferLength = screenInfo.xres * screenInfo.yres * depth;
+        pixelBuffer = (unsigned char *) malloc(pixelBufferLength);
         if (pixelBuffer == NULL) {
             GLASS_LOG_SEVERE("Failed to allocate temporary pixel buffer");
             return JNI_FALSE;
@@ -379,16 +384,9 @@
         }
 
         fseek(fb, screenInfo.yoffset * screenInfo.xres * depth, SEEK_SET);
-        int numRead = fread(pixelBuffer, depth,
-                            screenInfo.xres * screenInfo.yres * depth, fb);
-
-        if (width < 1 || height < 1) {
-            GLASS_LOG_SEVERE("Failed. width/height values must be at least = 1");
-            free(pixelBuffer);
-            fclose(fb);
-            GLASS_LOG_FINE("fclose(%s)", FB_DEVICE);
-            return JNI_FALSE;
-        }
+        int numRead = fread(pixelBuffer, 1,
+                            pixelBufferLength,
+                            fb);
 
         if (x < 0) {
             dst += -x * 4;
@@ -432,7 +430,7 @@
             free(pixelBuffer);
             fclose(fb);
             GLASS_LOG_FINE("fclose(%s)", FB_DEVICE);
-            GLASS_LOG_SEVERE("Failed to take a snapshot, some of parameters are illigal");
+            GLASS_LOG_SEVERE("Failed to take a snapshot, some of parameters are illegal");
             return JNI_FALSE;
         }
 
--- a/glass/glass-lib-windows/src/CommonDialogs.cpp	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass-lib-windows/src/CommonDialogs.cpp	Tue Apr 09 09:33:44 2013 -0700
@@ -92,7 +92,7 @@
  */
 JNIEXPORT jobject JNICALL Java_com_sun_glass_ui_win_WinCommonDialogs__1showFileChooser
   (JNIEnv *env, jobject jThis, jlong owner, jstring jFolder, jstring jFilename, jstring jTitle, jint type,
-        jboolean multipleMode, jobjectArray jFilters)
+        jboolean multipleMode, jobjectArray jFilters, jint defaultFilterIndex)
 {
     CommonDialogOwner cdo((HWND)jlong_to_ptr(owner));
     JString folder(env, jFolder);
@@ -100,9 +100,9 @@
     JString title(env, jTitle);
 
     if (IS_WINVISTA) {
-        return COMFileChooser_Show((HWND)jlong_to_ptr(owner), folder, filename, title, type, multipleMode, jFilters);
+        return COMFileChooser_Show((HWND)jlong_to_ptr(owner), folder, filename, title, type, multipleMode, jFilters, defaultFilterIndex);
     } else {
-        return StandardFileChooser_Show((HWND)jlong_to_ptr(owner), folder, filename, title, type, multipleMode, jFilters);
+        return StandardFileChooser_Show((HWND)jlong_to_ptr(owner), folder, filename, title, type, multipleMode, jFilters, defaultFilterIndex);
     }
 }
 
--- a/glass/glass-lib-windows/src/CommonDialogs_COM.cpp	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass-lib-windows/src/CommonDialogs_COM.cpp	Tue Apr 09 09:33:44 2013 -0700
@@ -95,7 +95,7 @@
     return ext;
 }
 
-void SetFilters(IFileDialogPtr pDialog, jobjectArray jFilters)
+void SetFilters(IFileDialogPtr pDialog, jobjectArray jFilters, jint defaultFilterIndex)
 {
     JNIEnv *env = GetEnv();
 
@@ -110,7 +110,11 @@
     }
 
     OLE_TRY
+    OLE_HRT( pDialog->SetDefaultExtension(L"") );
     OLE_HRT( pDialog->SetFileTypes(size, filterSpec) );
+    if (size > 0) {
+        OLE_HRT( pDialog->SetFileTypeIndex(defaultFilterIndex + 1) ); // 1-based index required
+    }
     OLE_CATCH
 
     for (int i = 0; i < size; i++) {
@@ -175,7 +179,7 @@
 }
 
 jobject COMFileChooser_Show(HWND owner, LPCTSTR folder, LPCTSTR filename, LPCTSTR title, jint type,
-                                 jboolean multipleMode, jobjectArray jFilters)
+                                 jboolean multipleMode, jobjectArray jFilters, jint defaultFilterIndex)
 {
     OLEHolder _ole_;
     IFileDialogPtr pDialog;
@@ -219,7 +223,7 @@
     }
 
     if (jFilters != NULL) {
-        SetFilters(pDialog, jFilters);
+        SetFilters(pDialog, jFilters, defaultFilterIndex);
     }
 
     OLE_HR = pDialog->Show(owner);
--- a/glass/glass-lib-windows/src/CommonDialogs_COM.h	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass-lib-windows/src/CommonDialogs_COM.h	Tue Apr 09 09:33:44 2013 -0700
@@ -27,7 +27,7 @@
 #define _COMMONDIALOGS_COM_INCLUDED_
 
 jobject COMFileChooser_Show(HWND owner, LPCTSTR folder, LPCTSTR filename, LPCTSTR title, jint type,
-                                 jboolean multipleMode, jobjectArray jFilters);
+                                 jboolean multipleMode, jobjectArray jFilters, jint defaultFilterIndex);
 
 jstring COMFolderChooser_Show(HWND owner, LPCTSTR folder, LPCTSTR title);
 
--- a/glass/glass-lib-windows/src/CommonDialogs_Standard.cpp	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass-lib-windows/src/CommonDialogs_Standard.cpp	Tue Apr 09 09:33:44 2013 -0700
@@ -170,7 +170,7 @@
 } 
 
 jobject StandardFileChooser_Show(HWND owner, LPCTSTR folder, LPCTSTR filename, LPCTSTR title, jint type,
-                                      jboolean multipleMode, jobjectArray jFilters)
+                                      jboolean multipleMode, jobjectArray jFilters, jint defaultFilterIndex)
 {
     DNTString files(MAX_PATH);
     DNTString filters(MAX_PATH);
@@ -189,7 +189,7 @@
     ofn.lStructSize       = sizeof(OPENFILENAME);
     ofn.hwndOwner         = owner;
     ofn.lpstrFilter       = filters;
-    ofn.nFilterIndex      = 1;
+    ofn.nFilterIndex      = defaultFilterIndex + 1; // nFilterIndex is 1-based
     ofn.lpstrFile         = files;
     ofn.nMaxFile          = MAX_PATH;
     ofn.lpstrInitialDir   = folder;
--- a/glass/glass-lib-windows/src/CommonDialogs_Standard.h	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass-lib-windows/src/CommonDialogs_Standard.h	Tue Apr 09 09:33:44 2013 -0700
@@ -27,7 +27,7 @@
 #define _COMMONDIALOGS_STANDARD_INCLUDED_
 
 jobject StandardFileChooser_Show(HWND owner, LPCTSTR folder, LPCTSTR filename, LPCTSTR title, jint type,
-                                      jboolean multipleMode, jobjectArray jFilters);
+                                      jboolean multipleMode, jobjectArray jFilters, jint defaultFilterIndex);
 
 jstring StandardFolderChooser_Show(HWND owner, LPCTSTR folder, LPCTSTR title);
 
--- a/glass/glass/build.xml	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/build.xml	Tue Apr 09 09:33:44 2013 -0700
@@ -16,6 +16,13 @@
     <property name="jfx.logging.dir" value="${rt.dist.root.dir}/javafx-logging"/>
     <property name="jfx.logging.jar" value="${jfx.logging.dir}/dist/javafx-logging.jar"/>
 
+    <condition property="needLens">
+      <or>
+         <isset property="isLinux"/>
+         <isset property="isAndroid"/>
+      </or>
+    </condition>
+
     <target name="init">
         <mkdir dir="${glass-java.class.dir}" />
         <mkdir dir="${glass-java.dist.dir}" />
@@ -48,7 +55,7 @@
             <exclude name="com/sun/glass/events/mac/" unless="isMacOSX" />
             <exclude name="com/sun/glass/ui/gtk/" unless="isLinux" />
             <exclude name="com/sun/glass/ui/ios/" unless="isIOS" />
-            <exclude name="com/sun/glass/ui/lens/" unless="isLinux" />
+            <exclude name="com/sun/glass/ui/lens/" unless="needLens" />
             <exclude name="com/sun/glass/ui/mac/" unless="isMacOSX" />
             <exclude name="com/sun/glass/ui/win/" unless="isWindows" />
             <exclude name="com/sun/glass/ui/x11/" unless="isLinux" />
--- a/glass/glass/src/com/sun/glass/ui/Application.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/Application.java	Tue Apr 09 09:33:44 2013 -0700
@@ -581,7 +581,7 @@
     }
 
     protected abstract FileChooserResult staticCommonDialogs_showFileChooser(Window owner, String folder, String filename, String title, int type,
-                                                     boolean multipleMode, ExtensionFilter[] extensionFilters);
+                                                     boolean multipleMode, ExtensionFilter[] extensionFilters, int defaultFilterIndex);
 
     protected abstract File staticCommonDialogs_showFolderChooser(Window owner, String folder, String title);
 
--- a/glass/glass/src/com/sun/glass/ui/CommonDialogs.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/CommonDialogs.java	Tue Apr 09 09:33:44 2013 -0700
@@ -175,6 +175,7 @@
      * @param type              the type of the file chooser, one of the constants from {@link Type}
      * @param multipleMode      enables or disable multiple file selections
      * @param extensionFilters  the filters of the file chooser
+     * @param defaultFilterIndex the zero-based index of the filter selected by default
      * @throws IllegalArgumentException
      *         if the initial folder is an invalid folder;
      *         if the type doesn't equal one of the constants from {@link Type}
@@ -183,7 +184,7 @@
      *         results object.
      */
     public static FileChooserResult showFileChooser(Window owner, File folder, String filename, String title, int type,
-                                        boolean multipleMode, List<ExtensionFilter> extensionFilters)
+                                        boolean multipleMode, List<ExtensionFilter> extensionFilters, int defaultFilterIndex)
     {
         Application.checkEventThread();
         String _folder = convertFolder(folder);
@@ -199,9 +200,16 @@
         if (extensionFilters != null) {
             _extensionFilters = extensionFilters.toArray(new ExtensionFilter[extensionFilters.size()]);
         }
+        
+        if (extensionFilters == null
+                || extensionFilters.isEmpty()
+                || defaultFilterIndex < 0
+                || defaultFilterIndex >= extensionFilters.size()) {
+            defaultFilterIndex = 0;
+        }
 
         return Application.GetApplication().
-            staticCommonDialogs_showFileChooser(owner, _folder, filename, convertTitle(title), type, multipleMode, _extensionFilters);
+            staticCommonDialogs_showFileChooser(owner, _folder, filename, convertTitle(title), type, multipleMode, _extensionFilters, defaultFilterIndex);
     }
 
     /**
--- a/glass/glass/src/com/sun/glass/ui/gtk/GtkApplication.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/gtk/GtkApplication.java	Tue Apr 09 09:33:44 2013 -0700
@@ -42,7 +42,6 @@
 import java.nio.IntBuffer;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.util.List;
 import java.util.Map;
 
 final class GtkApplication extends Application implements InvokeLaterDispatcher.InvokeLaterSubmitter {
@@ -282,8 +281,12 @@
     @Override native protected Screen[] staticScreen_getScreens();
 
     @Override
-    protected FileChooserResult staticCommonDialogs_showFileChooser(Window owner, String folder, String filename, String title, int type, boolean multipleMode, ExtensionFilter[] extensionFilters) {
-        return GtkCommonDialogs.showFileChooser(owner, folder, filename, title, type, multipleMode, extensionFilters);
+    protected FileChooserResult staticCommonDialogs_showFileChooser(
+            Window owner, String folder, String filename, String title,
+            int type, boolean multipleMode, ExtensionFilter[] extensionFilters, int defaultFilterIndex) {
+
+        return GtkCommonDialogs.showFileChooser(owner, folder, filename, title,
+                type, multipleMode, extensionFilters, defaultFilterIndex);
     }
 
     @Override
--- a/glass/glass/src/com/sun/glass/ui/gtk/GtkCommonDialogs.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/gtk/GtkCommonDialogs.java	Tue Apr 09 09:33:44 2013 -0700
@@ -29,7 +29,6 @@
 import com.sun.glass.ui.Window;
 
 import java.io.File;
-import java.util.List;
 
 final class GtkCommonDialogs {
  
@@ -40,7 +39,8 @@
                                             String title,
                                             int type,
                                             boolean multipleMode,
-                                            ExtensionFilter[] extensionFilters);
+                                            ExtensionFilter[] extensionFilters,
+                                            int defaultFilterIndex);
 
     private static native String _showFolderChooser(long parent,
                                                     String folder,
@@ -52,11 +52,11 @@
                                     String title,
                                     int type,
                                     boolean multipleMode,
-                                    ExtensionFilter[] extensionFilters) {
+                                    ExtensionFilter[] extensionFilters, int defaultFilterIndex) {
 
         if (owner != null) owner.setEnabled(false);
         FileChooserResult result = _showFileChooser(owner == null? 0L : owner.getNativeHandle(),
-                folder, filename, title, type, multipleMode, extensionFilters);
+                folder, filename, title, type, multipleMode, extensionFilters, defaultFilterIndex);
         if (owner != null) owner.setEnabled(true);
         return result;
     }
--- a/glass/glass/src/com/sun/glass/ui/ios/IosApplication.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/ios/IosApplication.java	Tue Apr 09 09:33:44 2013 -0700
@@ -189,7 +189,7 @@
     }
 
     @Override
-    protected FileChooserResult staticCommonDialogs_showFileChooser(Window owner, String folder, String filename, String title, int type, boolean multipleMode, ExtensionFilter[] extensionFilters) {
+    protected FileChooserResult staticCommonDialogs_showFileChooser(Window owner, String folder, String filename, String title, int type, boolean multipleMode, ExtensionFilter[] extensionFilters, int defaultFilterIndex) {
         return new FileChooserResult();
     }
 
--- a/glass/glass/src/com/sun/glass/ui/lens/LensApplication.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/lens/LensApplication.java	Tue Apr 09 09:33:44 2013 -0700
@@ -1473,11 +1473,11 @@
                                         String filename,
                                         String title, int type,
                                         boolean multipleMode,
-                                        ExtensionFilter[] extensionFilters) {
+                                        ExtensionFilter[] extensionFilters, int defaultFilterIndex) {
         //TODO: support FileChooserResult
         return new FileChooserResult(LensCommonDialogs.showFileChooser_impl(folder, title, type,
                                                       multipleMode,
-                                                      extensionFilters), null);
+                                                      extensionFilters, defaultFilterIndex), null);
     }
 
     @Override
--- a/glass/glass/src/com/sun/glass/ui/lens/LensCommonDialogs.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/lens/LensCommonDialogs.java	Tue Apr 09 09:33:44 2013 -0700
@@ -39,7 +39,8 @@
 final class LensCommonDialogs {
 
     static List<File> showFileChooser_impl(String folder, String title, int type,
-                                         boolean multipleMode, ExtensionFilter[] extensionFilters) {
+                                         boolean multipleMode, ExtensionFilter[] extensionFilters,
+                                         int defaultFilterIndex) {
 
         LensLogger.getLogger().severe("Not implemented");
         throw new UnsupportedOperationException("not implmented");
--- a/glass/glass/src/com/sun/glass/ui/mac/MacApplication.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/mac/MacApplication.java	Tue Apr 09 09:33:44 2013 -0700
@@ -210,9 +210,12 @@
     }
 
     @Override protected FileChooserResult staticCommonDialogs_showFileChooser(Window owner, String folder, String filename, String title, int type,
-                                                     boolean multipleMode, ExtensionFilter[] extensionFilters) {
+                                                     boolean multipleMode, ExtensionFilter[] extensionFilters, int defaultFilterIndex) {
         //TODO: support FileChooserResult
-        return new FileChooserResult(MacCommonDialogs.showFileChooser_impl(owner, folder, filename, title, type, multipleMode, extensionFilters), null);
+        //TODO: support defaultFilterIndex
+        return new FileChooserResult(
+                MacCommonDialogs.showFileChooser_impl(owner, folder, filename,
+                title, type, multipleMode, extensionFilters, defaultFilterIndex), null);
     }
 
     @Override protected File staticCommonDialogs_showFolderChooser(Window owner, String folder, String title) {
--- a/glass/glass/src/com/sun/glass/ui/mac/MacCommonDialogs.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/mac/MacCommonDialogs.java	Tue Apr 09 09:33:44 2013 -0700
@@ -53,7 +53,7 @@
     private static native File _showFolderChooser(String folder, String title);
 
     static List<File> showFileChooser_impl(Window owner, String folder, String filename, String title, int type,
-                                         boolean multipleMode, ExtensionFilter[] extensionFilters) {
+                                         boolean multipleMode, ExtensionFilter[] extensionFilters, int defaultFilterIndex) {
         List<String> list = new ArrayList<String>();
         for (ExtensionFilter extension : extensionFilters) {
             for (String suffix : extension.getExtensions()) {
--- a/glass/glass/src/com/sun/glass/ui/swt/SWTApplication.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/swt/SWTApplication.java	Tue Apr 09 09:33:44 2013 -0700
@@ -306,7 +306,9 @@
     }
 
     @Override
-    protected FileChooserResult staticCommonDialogs_showFileChooser(Window owner, String folder, String filename, String title, int type, boolean multipleMode, ExtensionFilter[] extensionFilters) {
+    protected FileChooserResult staticCommonDialogs_showFileChooser(Window owner, String folder,
+                                    String filename, String title, int type, boolean multipleMode,
+                                    ExtensionFilter[] extensionFilters, int defaultFilterIndex) {
         int bits = SWT.APPLICATION_MODAL;
         if (multipleMode) bits |= SWT.MULTI;
         switch (type) {
@@ -326,6 +328,7 @@
         dialog.setFilterNames(filters);
         dialog.setFilterExtensions(extensions);
         dialog.setFilterPath(folder);
+        dialog.setFilterIndex(defaultFilterIndex);
         dialog.setFileName(filename);
         if (dialog.open() == null) return new FileChooserResult();
         String path = dialog.getFilterPath();
--- a/glass/glass/src/com/sun/glass/ui/win/WinApplication.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/win/WinApplication.java	Tue Apr 09 09:33:44 2013 -0700
@@ -207,9 +207,9 @@
     }
 
     @Override protected FileChooserResult staticCommonDialogs_showFileChooser(Window owner, String folder, String filename, String title, int type,
-                                             boolean multipleMode, ExtensionFilter[] extensionFilters) {
+                                             boolean multipleMode, ExtensionFilter[] extensionFilters, int defaultFilterIndex) {
         invokeLaterDispatcher.notifyEnteringNestedEventLoop();
-        return WinCommonDialogs.showFileChooser_impl(owner, folder, filename, title, type, multipleMode, extensionFilters);
+        return WinCommonDialogs.showFileChooser_impl(owner, folder, filename, title, type, multipleMode, extensionFilters, defaultFilterIndex);
     }
 
     @Override protected File staticCommonDialogs_showFolderChooser(Window owner, String folder, String title) {
--- a/glass/glass/src/com/sun/glass/ui/win/WinCommonDialogs.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/glass/glass/src/com/sun/glass/ui/win/WinCommonDialogs.java	Tue Apr 09 09:33:44 2013 -0700
@@ -43,18 +43,18 @@
     }
 
     private static native FileChooserResult _showFileChooser(long owner, String folder, String filename, String title, int type,
-                                                    boolean multipleMode, ExtensionFilter[] extensionFilters);
+                                                    boolean multipleMode, ExtensionFilter[] extensionFilters, int defaultFilterIndex);
 
     private static native String _showFolderChooser(long owner, String folder, String title);
 
     static FileChooserResult showFileChooser_impl(Window owner, String folder, String filename, String title, int type,
-                                         boolean multipleMode, ExtensionFilter[] extensionFilters) {
+                                         boolean multipleMode, ExtensionFilter[] extensionFilters, int defaultFilterIndex) {
         if (owner != null) {
             ((WinWindow)owner).setDeferredClosing(true);
         }
         try {
             return _showFileChooser(owner != null ? owner.getNativeWindow() : 0L,
-                    folder, filename, title, type, multipleMode, extensionFilters);
+                    folder, filename, title, type, multipleMode, extensionFilters, defaultFilterIndex);
         } finally {
             if (owner != null) {
                 ((WinWindow)owner).setDeferredClosing(false);
--- a/javafx-beans/src/com/sun/javafx/collections/ObservableListWrapper.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-beans/src/com/sun/javafx/collections/ObservableListWrapper.java	Tue Apr 09 09:33:44 2013 -0700
@@ -133,6 +133,11 @@
     }
 
     @Override
+    public boolean containsAll(Collection<?> c) {
+        return backingList.containsAll(c);
+    }
+
+    @Override
     public void clear() {
         if (elementObserver != null) {
             final int sz = size();
--- a/javafx-beans/src/com/sun/javafx/collections/ObservableSequentialListWrapper.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-beans/src/com/sun/javafx/collections/ObservableSequentialListWrapper.java	Tue Apr 09 09:33:44 2013 -0700
@@ -75,6 +75,26 @@
     }
 
     @Override
+    public boolean contains(Object o) {
+        return backingList.contains(o);
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+        return backingList.containsAll(c);
+    }
+
+    @Override
+    public int indexOf(Object o) {
+        return backingList.indexOf(o);
+    }
+
+    @Override
+    public int lastIndexOf(Object o) {
+        return backingList.lastIndexOf(o);
+    }
+
+    @Override
     public ListIterator<E> listIterator(final int index) {
         return new ListIterator<E>() {
 
--- a/javafx-beans/src/javafx/beans/property/BooleanProperty.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-beans/src/javafx/beans/property/BooleanProperty.java	Tue Apr 09 09:33:44 2013 -0700
@@ -34,23 +34,26 @@
 /**
  * This class provides a full implementation of a {@link Property} wrapping a
  * {@code boolean} value.
- * 
+ * <p>
  * The value of a {@code BooleanProperty} can be get and set with {@link #get()},
  * {@link #getValue()}, {@link #set(boolean)}, and {@link #setValue(Boolean)}.
- * 
+ * <p>
  * A property can be bound and unbound unidirectional with
  * {@link #bind(ObservableValue)} and {@link #unbind()}. Bidirectional bindings
  * can be created and removed with {@link #bindBidirectional(Property)} and
  * {@link #unbindBidirectional(Property)}.
- * 
+ * <p>
  * The context of a {@code BooleanProperty} can be read with {@link #getBean()}
  * and {@link #getName()}.
- * 
+ *
+ * <p>
+ * Note: setting or binding this property to a null value will set the property to "false". See {@link #setValue(java.lang.Boolean) }.
+ *
  * @see javafx.beans.value.ObservableBooleanValue
  * @see javafx.beans.value.WritableBooleanValue
  * @see ReadOnlyBooleanProperty
  * @see Property
- * 
+ *
  */
 public abstract class BooleanProperty extends ReadOnlyBooleanProperty implements
         Property<Boolean>, WritableBooleanValue {
@@ -87,7 +90,7 @@
     /**
      * Returns a string representation of this {@code BooleanProperty} object.
      * @return a string representation of this {@code BooleanProperty} object.
-     */ 
+     */
     @Override
     public String toString() {
         final Object bean = getBean();
@@ -103,7 +106,7 @@
         result.append("value: ").append(get()).append("]");
         return result.toString();
     }
-    
+
     /**
      * Returns a {@code BooleanProperty} that wraps a
      * {@link javafx.beans.property.Property}. If the
@@ -111,9 +114,9 @@
      * will be returned. Otherwise a new
      * {@code BooleanProperty} is created that is bound to
      * the {@code Property}.
-     * 
+     *
      * Note: null values in the source property will be interpreted as "false"
-     * 
+     *
      * @param property
      *            The source {@code Property}
      * @return A {@code BooleanProperty} that wraps the
@@ -139,7 +142,7 @@
             public String getName() {
                 return property.getName();
             }
-            
+
             @Override
             protected void finalize() throws Throwable {
                 try {
@@ -150,19 +153,19 @@
             }
         };
     }
-    
+
     /**
      * Creates an {@link javafx.beans.property.ObjectProperty} that holds the value
      * of this {@code BooleanProperty}. If the
      * value of this {@code BooleanProperty} changes, the value of the
      * {@code ObjectProperty} will be updated automatically.
-     * 
+     *
      * @return the new {@code ObjectProperty}
      */
     @Override
     public ObjectProperty<Boolean> asObject() {
         return new ObjectPropertyBase<Boolean> () {
-            
+
             {
                 BidirectionalBinding.bind(this, BooleanProperty.this);
             }
--- a/javafx-beans/src/javafx/beans/property/DoubleProperty.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-beans/src/javafx/beans/property/DoubleProperty.java	Tue Apr 09 09:33:44 2013 -0700
@@ -39,23 +39,25 @@
 
 /**
  * This class defines a {@link Property} wrapping a {@code double} value.
- * 
+ * <p>
  * The value of a {@code DoubleProperty} can be get and set with {@link #get()},
  * {@link #getValue()}, {@link #set(double)}, and {@link #setValue(Number)}.
- * 
+ * <p>
  * A property can be bound and unbound unidirectional with
  * {@link #bind(ObservableValue)} and {@link #unbind()}. Bidirectional bindings
  * can be created and removed with {@link #bindBidirectional(Property)} and
  * {@link #unbindBidirectional(Property)}.
- * 
+ * <p>
  * The context of a {@code DoubleProperty} can be read with {@link #getBean()}
  * and {@link #getName()}.
- * 
+ * <p>
+ * Note: setting or binding this property to a null value will set the property to "0.0". See {@link #setValue(java.lang.Number) }.
+ *
  * @see javafx.beans.value.ObservableDoubleValue
  * @see javafx.beans.value.WritableDoubleValue
  * @see ReadOnlyDoubleProperty
  * @see Property
- * 
+ *
  */
 public abstract class DoubleProperty extends ReadOnlyDoubleProperty implements
         Property<Number>, WritableDoubleValue {
@@ -92,7 +94,7 @@
     /**
      * Returns a string representation of this {@code DoubleProperty} object.
      * @return a string representation of this {@code DoubleProperty} object.
-     */ 
+     */
     @Override
     public String toString() {
         final Object bean = getBean();
@@ -108,40 +110,40 @@
         result.append("value: ").append(get()).append("]");
         return result.toString();
     }
-    
+
     /**
      * Returns a {@code DoubleProperty} that wraps a
-     * {@link javafx.beans.property.Property} and is 
+     * {@link javafx.beans.property.Property} and is
      * bidirectionally bound to it.
      * Changing this property will result in a change of the original property.
-     * 
+     *
      * <p>
      * This is very useful when bidirectionally binding an ObjectProperty<Double> and
      * a DoubleProperty.
-     * 
+     *
      * <blockquote><pre>
      *   DoubleProperty doubleProperty = new SimpleDoubleProperty(1.0);
      *   ObjectProperty&lt;Double&gt; objectProperty = new SimpleObjectProperty&lt;&gt;(2.0);
-     * 
+     *
      *   // Need to keep the reference as bidirectional binding uses weak references
      *   DoubleProperty objectAsDouble = DoubleProperty.doubleProperty(objectProperty);
-     *   
+     *
      *   doubleProperty.bindBidirectional(objectAsDouble);
-     * 
+     *
      * </pre></blockquote>
-     * 
+     *
      * Another approach is to convert the DoubleProperty to ObjectProperty using
      * {@link #asObject()} method.
      * <p>
      * Note: null values in the source property will be interpreted as 0.0
-     * 
+     *
      * @param property
      *            The source {@code Property}
      * @return A {@code DoubleProperty} that wraps the
      *         {@code Property}
      * @throws NullPointerException
      *             if {@code value} is {@code null}
-     * @see #asObject() 
+     * @see #asObject()
      */
     public static DoubleProperty doubleProperty(final Property<Double> property) {
         if (property == null) {
@@ -161,7 +163,7 @@
             public String getName() {
                 return property.getName();
             }
-            
+
             @Override
             protected void finalize() throws Throwable {
                 try {
@@ -174,27 +176,27 @@
     }
 
     /**
-     * Creates an {@link javafx.beans.property.ObjectProperty} 
+     * Creates an {@link javafx.beans.property.ObjectProperty}
      * that bidirectionally bound to this {@code DoubleProperty}. If the
      * value of this {@code DoubleProperty} changes, the value of the
      * {@code ObjectProperty} will be updated automatically and vice-versa.
-     * 
+     *
      * <p>
      * Can be used for binding an ObjectProperty to DoubleProperty.
-     * 
+     *
      * <blockquote><pre>
      *   DoubleProperty doubleProperty = new SimpleDoubleProperty(1.0);
      *   ObjectProperty&lt;Double&gt; objectProperty = new SimpleObjectProperty&lt;&gt;(2.0);
-     *   
+     *
      *   objectProperty.bind(doubleProperty.asObject());
      * </pre></blockquote>
-     * 
+     *
      * @return the new {@code ObjectProperty}
      */
     @Override
     public ObjectProperty<Double> asObject() {
         return new ObjectPropertyBase<Double> () {
-            
+
             {
                 BidirectionalBinding.bindNumber(this, DoubleProperty.this);
             }
@@ -220,6 +222,6 @@
 
         };
     }
-    
-    
+
+
 }
--- a/javafx-beans/src/javafx/beans/property/FloatProperty.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-beans/src/javafx/beans/property/FloatProperty.java	Tue Apr 09 09:33:44 2013 -0700
@@ -33,23 +33,25 @@
 
 /**
  * This class defines a {@link Property} wrapping a {@code float} value.
- * 
+ * <p>
  * The value of a {@code FloatProperty} can be get and set with {@link #get()},
  * {@link #getValue()}, {@link #set(float)}, and {@link #setValue(Number)}.
- * 
+ * <p>
  * A property can be bound and unbound unidirectional with
  * {@link #bind(ObservableValue)} and {@link #unbind()}. Bidirectional bindings
  * can be created and removed with {@link #bindBidirectional(Property)} and
  * {@link #unbindBidirectional(Property)}.
- * 
+ * <p>
  * The context of a {@code FloatProperty} can be read with {@link #getBean()}
  * and {@link #getName()}.
- * 
+ * <p>
+ * Note: setting or binding this property to a null value will set the property to "0.0". See {@link #setValue(java.lang.Number) }.
+ *
  * @see javafx.beans.value.ObservableFloatValue
  * @see javafx.beans.value.WritableFloatValue
  * @see ReadOnlyFloatProperty
  * @see Property
- * 
+ *
  */
 public abstract class FloatProperty extends ReadOnlyFloatProperty implements
         Property<Number>, WritableFloatValue {
@@ -86,7 +88,7 @@
     /**
      * Returns a string representation of this {@code FloatProperty} object.
      * @return a string representation of this {@code FloatProperty} object.
-     */ 
+     */
     @Override
     public String toString() {
         final Object bean = getBean();
@@ -102,41 +104,41 @@
         result.append("value: ").append(get()).append("]");
         return result.toString();
     }
-    
+
     /**
      * Returns a {@code FloatProperty} that wraps a
-     * {@link javafx.beans.property.Property} and is 
+     * {@link javafx.beans.property.Property} and is
      * bidirectionally bound to it.
      * Changing this property will result in a change of the original property.
-     * 
+     *
      * <p>
      * This is very useful when bidirectionally binding an ObjectProperty<Float> and
      * a FloatProperty.
-     * 
+     *
      * <blockquote><pre>
      *   FloatProperty floatProperty = new SimpleFloatProperty(1.0f);
      *   ObjectProperty&lt;Float&gt; objectProperty = new SimpleObjectProperty&lt;&gt;(2.0f);
-     * 
+     *
      *   // Need to keep the reference as bidirectional binding uses weak references
      *   FloatProperty objectAsFloat = FloatProperty.floatProperty(objectProperty);
-     *   
+     *
      *   floatProperty.bindBidirectional(objectAsFloat);
-     * 
+     *
      * </pre></blockquote>
-     * 
+     *
      * Another approach is to convert the FloatProperty to ObjectProperty using
      * {@link #asObject()} method.
-     * 
+     *
      * <p>
      * Note: null values in the source property will be interpreted as 0f
-     * 
+     *
      * @param property
      *            The source {@code Property}
      * @return A {@code FloatProperty} that wraps the
      *         {@code Property}
      * @throws NullPointerException
      *             if {@code value} is {@code null}
-     * @see #asObject() 
+     * @see #asObject()
      */
      public static FloatProperty floatProperty(final Property<Float> property) {
         if (property == null) {
@@ -156,7 +158,7 @@
             public String getName() {
                 return property.getName();
             }
-            
+
             @Override
             protected void finalize() throws Throwable {
                 try {
@@ -189,7 +191,7 @@
     @Override
     public ObjectProperty<Float> asObject() {
         return new ObjectPropertyBase<Float> () {
-            
+
             {
                 BidirectionalBinding.bindNumber(this, FloatProperty.this);
             }
@@ -215,5 +217,5 @@
 
         };
     }
-    
+
 }
--- a/javafx-beans/src/javafx/beans/property/IntegerProperty.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-beans/src/javafx/beans/property/IntegerProperty.java	Tue Apr 09 09:33:44 2013 -0700
@@ -33,23 +33,25 @@
 
 /**
  * This class defines a {@link Property} wrapping an {@code int} value.
- * 
+ * <p>
  * The value of an {@code IntegerProperty} can be get and set with {@link #get()},
  * {@link #getValue()}, {@link #set(int)}, and {@link #setValue(Number)}.
- * 
+ * <p>
  * A property can be bound and unbound unidirectional with
  * {@link #bind(ObservableValue)} and {@link #unbind()}. Bidirectional bindings
  * can be created and removed with {@link #bindBidirectional(Property)} and
  * {@link #unbindBidirectional(Property)}.
- * 
+ * <p>
  * The context of a {@code IntegerProperty} can be read with {@link #getBean()}
  * and {@link #getName()}.
- * 
+ * <p>
+ * Note: setting or binding this property to a null value will set the property to "0.0". See {@link #setValue(java.lang.Number) }.
+ *
  * @see javafx.beans.value.ObservableIntegerValue
  * @see javafx.beans.value.WritableIntegerValue
  * @see ReadOnlyIntegerProperty
  * @see Property
- * 
+ *
  */
 public abstract class IntegerProperty extends ReadOnlyIntegerProperty implements
         Property<Number>, WritableIntegerValue {
@@ -86,7 +88,7 @@
     /**
      * Returns a string representation of this {@code IntegerProperty} object.
      * @return a string representation of this {@code IntegerProperty} object.
-     */ 
+     */
     @Override
     public String toString() {
         final Object bean = getBean();
@@ -102,41 +104,41 @@
         result.append("value: ").append(get()).append("]");
         return result.toString();
     }
-    
+
     /**
      * Returns a {@code IntegerProperty} that wraps a
-     * {@link javafx.beans.property.Property} and is 
+     * {@link javafx.beans.property.Property} and is
      * bidirectionally bound to it.
      * Changing this property will result in a change of the original property.
-     * 
+     *
      * <p>
      * This is very useful when bidirectionally binding an ObjectProperty<Integer> and
      * a IntegerProperty.
-     * 
+     *
      * <blockquote><pre>
      *   IntegerProperty integerProperty = new SimpleIntegerProperty(1);
      *   ObjectProperty&lt;Integer&gt; objectProperty = new SimpleObjectProperty&lt;&gt;(2);
-     * 
+     *
      *   // Need to keep the reference as bidirectional binding uses weak references
      *   IntegerProperty objectAsInteger = IntegerProperty.integerProperty(objectProperty);
-     *   
+     *
      *   integerProperty.bindBidirectional(objectAsInteger);
-     * 
+     *
      * </pre></blockquote>
-     * 
+     *
      * Another approach is to convert the IntegerProperty to ObjectProperty using
      * {@link #asObject()} method.
-     * 
+     *
      * <p>
      * Note: null values in the source property will be interpreted as 0
-     * 
+     *
      * @param property
      *            The source {@code Property}
      * @return A {@code IntegerProperty} that wraps the
      *         {@code Property}
      * @throws NullPointerException
      *             if {@code value} is {@code null}
-     * @see #asObject() 
+     * @see #asObject()
      */
      public static IntegerProperty integerProperty(final Property<Integer> property) {
         if (property == null) {
@@ -156,7 +158,7 @@
             public String getName() {
                 return property.getName();
             }
-            
+
             @Override
             protected void finalize() throws Throwable {
                 try {
@@ -169,27 +171,27 @@
     }
 
      /**
-     * Creates an {@link javafx.beans.property.ObjectProperty} 
+     * Creates an {@link javafx.beans.property.ObjectProperty}
      * that bidirectionally bound to this {@code IntegerProperty}. If the
      * value of this {@code IntegerProperty} changes, the value of the
      * {@code ObjectProperty} will be updated automatically and vice-versa.
-     * 
+     *
      * <p>
      * Can be used for binding an ObjectProperty to IntegerProperty.
-     * 
+     *
      * <blockquote><pre>
      *   IntegerProperty integerProperty = new SimpleIntegerProperty(1);
      *   ObjectProperty&lt;Integer&gt; objectProperty = new SimpleObjectProperty&lt;&gt;(2);
-     *   
+     *
      *   objectProperty.bind(integerProperty.asObject());
      * </pre></blockquote>
-     * 
+     *
      * @return the new {@code ObjectProperty}
      */
     @Override
     public ObjectProperty<Integer> asObject() {
         return new ObjectPropertyBase<Integer> () {
-            
+
             {
                 BidirectionalBinding.bindNumber(this, IntegerProperty.this);
             }
--- a/javafx-beans/src/javafx/beans/property/LongProperty.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-beans/src/javafx/beans/property/LongProperty.java	Tue Apr 09 09:33:44 2013 -0700
@@ -33,23 +33,24 @@
 
 /**
  * This class defines a {@link Property} wrapping a {@code long} value.
- * 
+ * <p>
  * The value of a {@code LongProperty} can be get and set with {@link #get()},
  * {@link #getValue()}, {@link #set(long)}, and {@link #setValue(Number)}.
- * 
+ * <p>
  * A property can be bound and unbound unidirectional with
  * {@link #bind(ObservableValue)} and {@link #unbind()}. Bidirectional bindings
  * can be created and removed with {@link #bindBidirectional(Property)} and
  * {@link #unbindBidirectional(Property)}.
- * 
+ * <p>
  * The context of a {@code LongProperty} can be read with {@link #getBean()}
  * and {@link #getName()}.
- * 
+ * <p>
+ * Note: setting or binding this property to a null value will set the property to "0.0". See {@link #setValue(java.lang.Number) }.
  * @see javafx.beans.value.ObservableLongValue
  * @see javafx.beans.value.WritableLongValue
  * @see ReadOnlyLongProperty
  * @see Property
- * 
+ *
  */
 public abstract class LongProperty extends ReadOnlyLongProperty implements
         Property<Number>, WritableLongValue {
@@ -86,7 +87,7 @@
     /**
      * Returns a string representation of this {@code LongProperty} object.
      * @return a string representation of this {@code LongProperty} object.
-     */ 
+     */
     @Override
     public String toString() {
         final Object bean = getBean();
@@ -101,41 +102,41 @@
         result.append("value: ").append(get()).append("]");
         return result.toString();
     }
-    
+
     /**
      * Returns a {@code LongProperty} that wraps a
-     * {@link javafx.beans.property.Property} and is 
+     * {@link javafx.beans.property.Property} and is
      * bidirectionally bound to it.
      * Changing this property will result in a change of the original property.
-     * 
+     *
      * <p>
      * This is very useful when bidirectionally binding an ObjectProperty<Long> and
      * a LongProperty.
-     * 
+     *
      * <blockquote><pre>
      *   LongProperty longProperty = new SimpleLongProperty(1L);
      *   ObjectProperty&lt;Long&gt; objectProperty = new SimpleObjectProperty&lt;&gt;(2L);
-     * 
+     *
      *   // Need to keep the reference as bidirectional binding uses weak references
      *   LongProperty objectAsLong = LongProperty.longProperty(objectProperty);
-     *   
+     *
      *   longProperty.bindBidirectional(objectAsLong);
-     * 
+     *
      * </pre></blockquote>
-     * 
+     *
      * Another approach is to convert the LongProperty to ObjectProperty using
      * {@link #asObject()} method.
-     * 
+     *
      * <p>
      * Note: null values in the source property will be interpreted as 0L
-     * 
+     *
      * @param property
      *            The source {@code Property}
      * @return A {@code LongProperty} that wraps the
      *         {@code Property}
      * @throws NullPointerException
      *             if {@code value} is {@code null}
-     * @see #asObject() 
+     * @see #asObject()
      */
      public static LongProperty longProperty(final Property<Long> property) {
         if (property == null) {
@@ -155,7 +156,7 @@
             public String getName() {
                 return property.getName();
             }
-            
+
             @Override
             protected void finalize() throws Throwable {
                 try {
@@ -168,27 +169,27 @@
     }
 
      /**
-     * Creates an {@link javafx.beans.property.ObjectProperty} 
+     * Creates an {@link javafx.beans.property.ObjectProperty}
      * that bidirectionally bound to this {@code LongProperty}. If the
      * value of this {@code LongProperty} changes, the value of the
      * {@code ObjectProperty} will be updated automatically and vice-versa.
-     * 
+     *
      * <p>
      * Can be used for binding an ObjectProperty to LongProperty.
-     * 
+     *
      * <blockquote><pre>
      *   LongProperty longProperty = new SimpleLongProperty(1L);
      *   ObjectProperty&lt;Long&gt; objectProperty = new SimpleObjectProperty&lt;&gt;(2L);
-     *   
+     *
      *   objectProperty.bind(longProperty.asObject());
      * </pre></blockquote>
-     * 
+     *
      * @return the new {@code ObjectProperty}
      */
     @Override
     public ObjectProperty<Long> asObject() {
         return new ObjectPropertyBase<Long> () {
-            
+
             {
                 BidirectionalBinding.bindNumber(this, LongProperty.this);
             }
--- a/javafx-common/src/com/sun/javafx/PlatformUtil.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-common/src/com/sun/javafx/PlatformUtil.java	Tue Apr 09 09:33:44 2013 -0700
@@ -78,13 +78,14 @@
             doEGLCompositing = false;
     }
 
+    private static final boolean ANDROID = "android".equals(System.getProperty("javafx.platform"));
     private static final boolean WINDOWS = os.startsWith("Windows");
     private static final boolean WINDOWS_VISTA_OR_LATER = WINDOWS && versionNumberGreaterThanOrEqualTo(6.0f);
     private static final boolean WINDOWS_7_OR_LATER = WINDOWS && versionNumberGreaterThanOrEqualTo(6.1f);
     private static final boolean MAC = os.startsWith("Mac");
-    private static final boolean LINUX = os.startsWith("Linux");
+    private static final boolean LINUX = os.startsWith("Linux") && !ANDROID;
     private static final boolean SOLARIS = os.startsWith("SunOS");
-    private static final boolean IOS = os.startsWith("iOS");
+    private static final boolean IOS = os.startsWith("iOS");    
 
     /**
      * Utility method used to determine whether the version number as
@@ -256,6 +257,7 @@
     private static void loadProperties() {
         final String vmname = System.getProperty("java.vm.name");
         final String arch = System.getProperty("os.arch");
+
         if (! (javafxPlatform != null ||
                 (arch != null && arch.equals("arm")) ||
                 (vmname != null && vmname.indexOf("Embedded") > 0))) {
@@ -270,17 +272,30 @@
                 // Then in the installation directory of the JRE
                 if (rtProperties.exists()) {
                     loadPropertiesFromFile(rtProperties);
-                } else {
-                    String javaHome = System.getProperty("java.home");
-                    File javaHomeProperties = new File(javaHome,
-                                                       "lib" + File.separator
-                                                       + propertyFilename);
-                    if (javaHomeProperties.exists()) {
-                        loadPropertiesFromFile(javaHomeProperties);
-                    } 
+                    return null;
+                } 
+                String javaHome = System.getProperty("java.home");
+                File javaHomeProperties = new File(javaHome,
+                                                   "lib" + File.separator
+                                                   + propertyFilename);
+                if (javaHomeProperties.exists()) {
+                    loadPropertiesFromFile(javaHomeProperties);
+                    return null;
+                } 
+                
+                String javafxRuntimePath = System.getProperty("javafx.runtime.path");
+                File javafxRuntimePathProperties = new File(javafxRuntimePath,
+                                                         File.separator + propertyFilename);
+                if (javafxRuntimePathProperties.exists()) {
+                   loadPropertiesFromFile(javafxRuntimePathProperties);
+                   return null;
                 }
                 return null;
             }
         });
     }
+    
+    public static boolean isAndroid() {
+       return ANDROID;
+    }
 }
--- a/javafx-embed-swing/build-closed.xml	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-embed-swing/build-closed.xml	Tue Apr 09 09:33:44 2013 -0700
@@ -14,7 +14,7 @@
     <property name="javac.classpath" refid="javac.closed.classpath.path"/>
 
     <condition property="runtime.excludes" value="javafx/embed/swing/SwingNode.java">
-        <not><contains string="${ant.java.version}" substring="1.8"/></not>
+        <not><contains string="${java.version}" substring="1.8"/></not>
     </condition>
 
     <import file="../build-defs.xml"/>
--- a/javafx-embed-swing/build-common.xml	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-embed-swing/build-common.xml	Tue Apr 09 09:33:44 2013 -0700
@@ -2,7 +2,7 @@
 <project name="javafx-embed-swing-common" default="jar" basedir=".">
 
     <condition property="runtime.excludes" value="javafx/embed/swing/SwingNode.java">
-        <not><contains string="${ant.java.version}" substring="1.8"/></not>
+        <not><contains string="${java.version}" substring="1.8"/></not>
     </condition>
 
 </project>
--- a/javafx-embed-swing/src/javafx/embed/swing/JFXPanel.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-embed-swing/src/javafx/embed/swing/JFXPanel.java	Tue Apr 09 09:33:44 2013 -0700
@@ -128,15 +128,15 @@
 
     private volatile EmbeddedWindow stage;
     private volatile Scene scene;
-    
+
     private final SwingDnD dnd;
 
     private EmbeddedStageInterface stagePeer;
     private EmbeddedSceneInterface scenePeer;
 
     // Dimensions of back buffer used to draw FX content
-    private int pWidth = -1;
-    private int pHeight = -1;
+    private int pWidth;
+    private int pHeight;
 
     // Preferred size set from FX
     private volatile int pPreferredWidth = -1;
@@ -147,6 +147,7 @@
     private volatile int screenX = 0;
     private volatile int screenY = 0;
 
+    // accessed on EDT only
     private BufferedImage pixelsIm;
 
     private volatile float opacity = 1.0f;
@@ -450,12 +451,7 @@
     protected void processComponentEvent(ComponentEvent e) {
         switch (e.getID()) {
             case ComponentEvent.COMPONENT_RESIZED: {
-                // It's quite possible to get negative values here, this is not
-                // what JavaFX embedded scenes/stages are ready to
-                pWidth = Math.max(0, getWidth());
-                pHeight = Math.max(0, getHeight());
-                resizePixels();
-                sendResizeEventToFX();
+                updateComponentSize();
                 break;
             }
             case ComponentEvent.COMPONENT_MOVED: {
@@ -471,6 +467,20 @@
         super.processComponentEvent(e);
     }
 
+    // called on EDT only
+    private void updateComponentSize() {
+        int oldWidth = pWidth;
+        int oldHeight = pHeight;
+        // It's quite possible to get negative values here, this is not
+        // what JavaFX embedded scenes/stages are ready to
+        pWidth = Math.max(0, getWidth());
+        pHeight = Math.max(0, getHeight());
+        if (oldWidth != pWidth || oldHeight != pHeight) {
+            resizePixels();
+            sendResizeEventToFX();
+        }
+    }
+
     // This methods should only be called on EDT
     private boolean updateScreenLocation() {
         synchronized (getTreeLock()) {
@@ -529,7 +539,7 @@
         boolean focused = (e.getID() == FocusEvent.FOCUS_GAINED);
         int focusCause = (focused ? AbstractEvents.FOCUSEVENT_ACTIVATED :
                                       AbstractEvents.FOCUSEVENT_DEACTIVATED);
-        
+
         if (focused && (e instanceof CausedFocusEvent)) {
             CausedFocusEvent ce = (CausedFocusEvent)e;
             if (ce.getCause() == CausedFocusEvent.Cause.TRAVERSAL_FORWARD) {
@@ -555,6 +565,7 @@
         super.processFocusEvent(e);
     }
 
+    // called on EDT only
     private void resizePixels() {
         if ((pWidth <= 0) || (pHeight <= 0)) {
             pixelsIm = null;
@@ -680,10 +691,11 @@
             }
         });
 
+        updateComponentSize(); // see RT-23603
+
         Platform.runLater(new Runnable() {
             @Override
             public void run() {
-                resizePixels();
                 if ((stage != null) && !stage.isShowing()) {
                     stage.show();
                     firstPanelShown = true;
@@ -705,10 +717,13 @@
                 if ((stage != null) && stage.isShowing()) {
                     stage.hide();
                 }
-                pixelsIm = null;
             }
         });
 
+        pixelsIm = null;
+        pWidth = 0;
+        pHeight = 0;
+
         super.removeNotify();
 
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
@@ -756,7 +771,9 @@
 
                 @Override
                 public void run() {
-                    scenePeer.setDragStartListener(dnd.getDragStartListener());
+                    if (scenePeer != null) {
+                        scenePeer.setDragStartListener(dnd.getDragStartListener());
+                    }
                 }
             });
         }
--- a/javafx-sg-common/src/com/sun/javafx/sg/BaseCacheFilter.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-sg-common/src/com/sun/javafx/sg/BaseCacheFilter.java	Tue Apr 09 09:33:44 2013 -0700
@@ -25,7 +25,6 @@
 
 package com.sun.javafx.sg;
 
-import com.sun.javafx.geom.BaseBounds;
 import com.sun.javafx.geom.Rectangle;
 import com.sun.scenario.effect.FilterContext;
 import com.sun.scenario.effect.ImageData;
@@ -210,8 +209,18 @@
         lastXDelta = lastXDelta * xformInfo[0];
         lastYDelta = lastYDelta * xformInfo[1];
 
+        if (cachedImageData != null) {
+            cachedImageData.getUntransformedImage().lock();
+            if (!cachedImageData.validate(fctx)) {
+                cachedImageData.getUntransformedImage().unlock();
+                invalidate();
+            }
+        }
         if (needToRenderCache(fctx, xform, xformInfo)) {
-            invalidate();
+            if (cachedImageData != null) {
+                cachedImageData.getUntransformedImage().unlock();
+                invalidate();
+            }
             // Update the cachedXform to the current xform (ignoring translate).
             cachedXform.setTransform(mxx, myx, mxy, myy, 0.0, 0.0);
             cachedScaleX = xformInfo[0];
@@ -263,6 +272,7 @@
             impl_renderNodeToScreen(implGraphics, xform);
         } else {
             impl_renderCacheToScreen(implGraphics, implImage, mxt, myt);
+            implImage.unlock();
         }
     }
 
@@ -302,10 +312,12 @@
 
     /*
      * Do we need to regenerate the cached image?
+     * Assumes that caller locked and validated the cachedImageData.untximage
+     * if not null...
      */
-    boolean needToRenderCache(FilterContext fctx, BaseTransform renderXform,
-                              double[] xformInfo) {
-        if (cachedImageData == null || !cachedImageData.validate(fctx)) {
+    private boolean needToRenderCache(FilterContext fctx, BaseTransform renderXform,
+                                      double[] xformInfo) {
+        if (cachedImageData == null) {
             return true;
         }
         
@@ -411,6 +423,10 @@
 
     protected void imageDataUnref() {
         if (cachedImageData != null) {
+            // While we hold on to this ImageData we leave the texture
+            // unlocked so it can be reclaimed, but the default unref()
+            // method assumes it was locked.
+            cachedImageData.getUntransformedImage().lock();
             cachedImageData.unref();
             cachedImageData = null;
         }
--- a/javafx-sg-prism/src/com/sun/javafx/sg/prism/EffectUtil.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-sg-prism/src/com/sun/javafx/sg/prism/EffectUtil.java	Tue Apr 09 09:33:44 2013 -0700
@@ -137,6 +137,8 @@
                                                         Texture.WrapMode.CLAMP_TO_EDGE);
             // We use a power-of-2 size so that we can get true CLAMP_TO_EDGE on all platforms
             assert itex.getWrapMode() == Texture.WrapMode.CLAMP_TO_EDGE;
+            itex.contentsUseful();
+            itex.makePermanent();
         }
         float r = shadow.getRadius();
         int texsize = itex.getPhysicalWidth();
@@ -250,6 +252,8 @@
                                                         Texture.WrapMode.CLAMP_TO_EDGE);
             // We use a power-of-2 size so that we can get true CLAMP_TO_EDGE on all platforms
             assert dtex.getWrapMode() == Texture.WrapMode.CLAMP_TO_EDGE;
+            dtex.contentsUseful();
+            dtex.makePermanent();
         }
         float r = shadow.getRadius();
         int texsize = dtex.getPhysicalWidth();
--- a/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGCanvas.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGCanvas.java	Tue Apr 09 09:33:44 2013 -0700
@@ -95,9 +95,18 @@
         }
        
         public boolean validate(Graphics resg, int tw, int th) {
-            int cw = (tex == null) ? 0 : tex.getContentWidth();
-            int ch = (tex == null) ? 0 : tex.getContentHeight();
-            if (tex == null || cw < tw || ch < th) {
+            int cw, ch;
+            boolean create;
+            if (tex == null) {
+                cw = ch = 0;
+                create = true;
+            } else {
+                cw = tex.getContentWidth();
+                ch = tex.getContentHeight();
+                tex.lock();
+                create = tex.isSurfaceLost() || cw < tw || ch < th;
+            }
+            if (create) {
                 RTTexture oldtex = tex;
                 ResourceFactory factory = resg.getResourceFactory();
                 RTTexture newtex =
@@ -117,6 +126,7 @@
                         }
                         g.setCompositeMode(CompositeMode.SRC_OVER);
                     }
+                    oldtex.unlock();
                     oldtex.dispose();
                 }
                 if (init_type == InitType.FILL_WHITE) {
@@ -443,11 +453,18 @@
             cv.dispose();
             return;
         }
-        cv.validate(g, tw, th);
+        if (cv.validate(g, tw, th)) {
+            // If the texture was recreated then we add a permanent
+            // "useful" and extra "lock" status to it.
+            cv.tex.contentsUseful();
+            cv.tex.makePermanent();
+            cv.tex.lock();
+        }
     }
 
     private void initClip() {
         if (clip.validate(cv.g, tw, th)) {
+            clip.tex.contentsUseful();
             for (Path2D clippath : clipStack) {
                 renderClip(clippath);
             }
@@ -460,6 +477,7 @@
         temp.g.setTransform(BaseTransform.IDENTITY_TRANSFORM);
         temp.g.fill(clippath);
         blendAthruBintoC(temp, Mode.SRC_IN, clip, null, CompositeMode.SRC, clip);
+        temp.tex.unlock();
     }
 
     private Rectangle applyEffectOnAintoC(Effect definput,
@@ -617,6 +635,8 @@
                     gr.drawTexture(tex,
                                    dx1, dy1, dx1 + highestPixelScale, dy1 + highestPixelScale,
                                    0, 0, 1, 1);
+                    tex.contentsNotUseful();
+                    tex.unlock();
                     break;
                 }
                 case PUT_ARGBPRE_BUF:
@@ -642,6 +662,8 @@
                     gr.drawTexture(tex,
                                    dx1, dy1, dx2, dy2,
                                    0, 0, w, h);
+                    tex.contentsNotUseful();
+                    tex.unlock();
                     gr.setCompositeMode(CompositeMode.SRC_OVER);
                     break;
                 }
@@ -747,11 +769,15 @@
                 case STROKE_TEXT:
                 {
                     RenderBuf dest;
-                    if (clipStack.isEmpty() && blendmode == Blend.Mode.SRC_OVER) {
-                        dest = cv;
-                    } else {
+                    if (!clipStack.isEmpty()) {
+                        initClip();
                         temp.validate(cv.g, tw, th);
                         dest = temp;
+                    } else if (blendmode != Blend.Mode.SRC_OVER) {
+                        temp.validate(cv.g, tw, th);
+                        dest = temp;
+                    } else {
+                        dest = cv;
                     }
                     if (effect != null) {
                         buf.save();
@@ -798,12 +824,15 @@
                             // back into the temp buffer.  We must use SRC
                             // mode here so that the erased (or reduced) pixels
                             // actually get reduced to their new alpha.
-                            dest = temp;
+                            // assert: dest == temp;
                             compmode = CompositeMode.SRC;
                         }
-                        initClip();
                         blendAthruBintoC(temp, Mode.SRC_IN, clip,
                                          TEMP_RECTBOUNDS, compmode, dest);
+                        clip.tex.unlock();
+                        if (dest != temp) {
+                            temp.tex.unlock();
+                        }
                     }
                     if (blendmode != Blend.Mode.SRC_OVER) {
                         // We always use SRC mode here because the results of
@@ -1010,6 +1039,7 @@
                     gr.drawTexture(tex,
                                    dx, dy, dx+dw, dy+dh,
                                    sx, sy, sx+sw, sy+sh);
+                    tex.unlock();
                 }
                 break;
             }
--- a/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGImageView.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGImageView.java	Tue Apr 09 09:33:44 2013 -0700
@@ -124,6 +124,7 @@
             } else {
                 coords.draw(texture, g, x, y);
             }
+            texture.unlock();
         } else {
             if (compoundImage == null) compoundImage = new CachingCompoundImage(image, maxSize);
             // coords is null iff there was no viewport specified, but
--- a/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGNode.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGNode.java	Tue Apr 09 09:33:44 2013 -0700
@@ -780,6 +780,8 @@
             try {
                 ret = Effect.getCompatibleImage(fctx,
                                           bounds.width, bounds.height);
+                Texture cachedTex = ((PrDrawable) ret).getTextureObject();
+                cachedTex.contentsUseful();
             } catch (Throwable e) {
                 ret = null;
             }
@@ -919,6 +921,12 @@
             int h = r.height - (int) Math.abs(yDelta);
 
             final Graphics g = drawable.createGraphics();
+            if (tempTexture != null) {
+                tempTexture.lock();
+                if (tempTexture.isSurfaceLost()) {
+                    tempTexture = null;
+                }
+            }
             if (tempTexture == null) {
                 tempTexture = g.getResourceFactory().
                     createRTTexture(drawable.getPhysicalWidth(), drawable.getPhysicalHeight(),
@@ -931,6 +939,7 @@
 
             g.clear();
             g.drawTexture(tempTexture, destX, destY, destX + w, destY + h, 0, 0, w, h);
+            tempTexture.unlock();
         }
 
         /**
--- a/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGRegion.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGRegion.java	Tue Apr 09 09:33:44 2013 -0700
@@ -504,6 +504,12 @@
                 // scaled region, or things won't look right (they'll looked scaled instead of vector-resized).
                 final boolean cache = backgroundCanBeCached && g.getTransformNoClone().isTranslateOrIdentity();
                 RTTexture cached = cache ? CACHE.getImage(g.getAssociatedScreen(), textureWidth, textureHeight, background, shape) : null;
+                if (cached != null) {
+                    cached.lock();
+                    if (cached.isSurfaceLost()) {
+                        cached = null;
+                    }
+                }
                 // If there is not a cached texture already, then we need to render everything
                 if (cached == null) {
                     // We will here check to see if we CAN cache the region background. If not, then
@@ -515,6 +521,7 @@
                         old = g;
                         cached = g.getResourceFactory().createRTTexture(textureWidth, textureHeight,
                                                                         WrapMode.CLAMP_TO_ZERO);
+                        cached.contentsUseful();
                         g = cached.createGraphics();
                         // Have to move the origin such that when rendering to x=0, we actually end up rendering
                         // at x=bounds.getMinX(). Otherwise anything rendered to the left of the origin would be lost
@@ -594,6 +601,7 @@
                     if (PulseLogger.PULSE_LOGGING_ENABLED) {
                         PulseLogger.PULSE_LOGGER.renderIncrementCounter("Cached Region shape image used");
                     }
+                    cached.unlock();
                 }
             }
 
@@ -648,6 +656,12 @@
                         backgroundCanBeCached &&
                         g.getTransformNoClone().isTranslateOrIdentity();
                 RTTexture cached = cache ? CACHE.getImage(g.getAssociatedScreen(), textureWidth, textureHeight, background) : null;
+                if (cached != null) {
+                    cached.lock();
+                    if (cached.isSurfaceLost()) {
+                        cached = null;
+                    }
+                }
                 // If there is not a cached texture already, then we need to render everything
                 if (cached == null) {
                     // We will here check to see if we CAN cache the region background. If not, then
@@ -661,6 +675,7 @@
                         width = cacheWidth;
                         cached = g.getResourceFactory().createRTTexture(textureWidth, textureHeight,
                                                                         WrapMode.CLAMP_TO_ZERO);
+                        cached.contentsUseful();
                         g = cached.createGraphics();
                         // Have to move the origin such that when rendering to x=0, we actually end up rendering
                         // at x=outsets.getLeft(). Otherwise anything rendered to the left of the origin would be lost
@@ -798,6 +813,7 @@
                             PulseLogger.PULSE_LOGGER.renderIncrementCounter("Cached Region background image used");
                         }
                     }
+                    cached.unlock();
                 }
 
                 final List<BackgroundImage> images = background.getImages();
@@ -824,6 +840,7 @@
                                     0, 0, width, height,
                                     0, 0, width/scale, height/scale
                             );
+                            texture.unlock();
                         } else {
                             // Other than "cover", all other modes need to pay attention to the repeat,
                             // size, and position in order to determine how to render. This next block
@@ -1761,6 +1778,7 @@
                 }
                 dstY += yIncrement;
             }
+            texture.unlock();
         }
     }
 
--- a/javafx-sg-prism/test/com/sun/javafx/sg/prism/TestGraphics.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-sg-prism/test/com/sun/javafx/sg/prism/TestGraphics.java	Tue Apr 09 09:33:44 2013 -0700
@@ -27,7 +27,6 @@
 
 import java.nio.Buffer;
 import com.sun.glass.ui.Screen;
-import com.sun.glass.ui.View;
 import com.sun.javafx.font.FontStrike;
 import com.sun.javafx.geom.RectBounds;
 import com.sun.javafx.geom.Shape;
@@ -51,6 +50,7 @@
 import com.sun.prism.camera.PrismCameraImpl;
 import com.sun.prism.impl.BaseContext;
 import com.sun.prism.impl.BaseGraphics;
+import com.sun.prism.impl.TextureResourcePool;
 import com.sun.prism.impl.VertexBuffer;
 import com.sun.prism.paint.Color;
 import com.sun.prism.shape.ShapeRep;
@@ -151,6 +151,7 @@
     private static class TestResourceFactory implements ResourceFactory {
         @Override public boolean isDeviceReady() { return true; }
 
+        @Override public TextureResourcePool getTextureResourcePool() { return null; }
         @Override public Texture createTexture(Image image, Texture.Usage usageHint, Texture.WrapMode wrapMode) { return null; }
         @Override public Texture createTexture(PixelFormat formatHint, Texture.Usage usageHint, Texture.WrapMode wrapMode, int w, int h) { return null; }
         @Override public Texture createTexture(MediaFrame frame) { return null; }
@@ -192,6 +193,14 @@
                 @Override public boolean getLinearFiltering() { return false; }
                 @Override public void setLinearFiltering(boolean linear) { }
                 @Override public void dispose() { }
+                @Override public void lock() { }
+                @Override public void unlock() { }
+                @Override public boolean isLocked() { return true; }
+                @Override public int getLockCount() { return 1; }
+                @Override public void assertLocked() { }
+                @Override public void makePermanent() { }
+                @Override public void contentsUseful() { }
+                @Override public void contentsNotUseful() { }
                 @Override public void setOpaque(boolean opaque) { }
             };
         }
--- a/javafx-ui-common/src/com/sun/javafx/runtime/async/AbstractAsyncOperation.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/src/com/sun/javafx/runtime/async/AbstractAsyncOperation.java	Tue Apr 09 09:33:44 2013 -0700
@@ -45,7 +45,7 @@
 public abstract class AbstractAsyncOperation<V> implements AsyncOperation,
                                                            Callable<V> {
 
-    private final FutureTask<V> future;
+    protected final FutureTask<V> future;
     protected final AsyncOperationListener listener;
 
     private int progressGranularity = 100;
--- a/javafx-ui-common/src/com/sun/javafx/tk/Toolkit.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/src/com/sun/javafx/tk/Toolkit.java	Tue Apr 09 09:33:44 2013 -0700
@@ -144,6 +144,8 @@
             return DEFAULT_TOOLKIT;
         } else if (PlatformUtil.isIOS()) {
             return DEFAULT_TOOLKIT;
+        } else if (PlatformUtil.isAndroid()) {
+           return DEFAULT_TOOLKIT;
         }
 
         throw new UnsupportedOperationException(System.getProperty("os.name") + " is not supported");
--- a/javafx-ui-common/src/javafx/scene/Node.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/src/javafx/scene/Node.java	Tue Apr 09 09:33:44 2013 -0700
@@ -5739,6 +5739,20 @@
         // overriden in Parent
     }
 
+    private Node getOrientationParent() {
+        final Node parentValue = getParent();
+        if (parentValue != null) {
+            return parentValue;
+        }
+
+        final Node subSceneValue = getSubScene();
+        if (subSceneValue != null) {
+            return subSceneValue;
+        }
+
+        return null;
+    }
+
     private byte calcEffectiveNodeOrientation() {
         final NodeOrientation nodeOrientationValue = getNodeOrientation();
         if (nodeOrientationValue != NodeOrientation.INHERIT) {
@@ -5747,7 +5761,7 @@
                        : EFFECTIVE_ORIENTATION_RTL;
         }
 
-        final Node parentValue = getParent();
+        final Node parentValue = getOrientationParent();
         if (parentValue != null) {
             return getEffectiveOrientation(parentValue.resolvedNodeOrientation);
         }
@@ -5775,7 +5789,7 @@
                        : AUTOMATIC_ORIENTATION_RTL;
         }
 
-        final Node parentValue = getParent();
+        final Node parentValue = getOrientationParent();
         if (parentValue != null) {
             // automatic node orientation is inherited
             return getAutomaticOrientation(parentValue.resolvedNodeOrientation);
@@ -5796,7 +5810,7 @@
     // A node has mirroring if the orientation differs from the parent
     // package private for testing
     final boolean hasMirroring() {
-        final Node parentValue = getParent();
+        final Node parentValue = getOrientationParent();
 
         final byte thisOrientation =
                 getAutomaticOrientation(resolvedNodeOrientation);
--- a/javafx-ui-common/src/javafx/scene/Parent.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/src/javafx/scene/Parent.java	Tue Apr 09 09:33:44 2013 -0700
@@ -130,9 +130,11 @@
                     for(int i = 0; i < removed.size(); i++) {
                         peer.addToRemoved(removed.get(i).impl_getPGNode());
                     }
-                    removed.clear();
                 }
             }
+            if (removed != null) {
+                removed.clear();
+            }
             pgChildrenSize = children.size();
             startIdx = pgChildrenSize;
         }
--- a/javafx-ui-common/src/javafx/scene/SubScene.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/src/javafx/scene/SubScene.java	Tue Apr 09 09:33:44 2013 -0700
@@ -437,6 +437,11 @@
         }
     }
 
+    @Override
+    void nodeResolvedOrientationChanged() {
+        getRoot().parentResolvedOrientationInvalidated();
+    }
+
     /***********************************************************************
      *                         CSS                                         *
      **********************************************************************/
--- a/javafx-ui-common/src/javafx/scene/input/Clipboard.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/src/javafx/scene/input/Clipboard.java	Tue Apr 09 09:33:44 2013 -0700
@@ -95,11 +95,9 @@
  * </pre></code>
  * <p>
  * In addition to the common or built in types, you may put any arbitrary data onto the
- * clipboard (assuming it is either a reference, or serializable. See more about
- * references later). The clipboard system in JavaFX utilizes the same system as Cocoa
- * for defining a hierarchical namespace for content types.
- * See http://en.wikipedia.org/wiki/Uniform_Type_Identifier.
+ * clipboard (assuming it is serializable).
  * <p>
+ * Content types are defined by the DataFormat objects.
  * The DataFormat class defines an immutable object, and there are a number of static final
  * fields for common DataFormat types. Of course application specific DataFormat types can also be
  * declared and used. The following two methods are equivalent (and the second call
--- a/javafx-ui-common/src/javafx/scene/layout/BorderPane.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/src/javafx/scene/layout/BorderPane.java	Tue Apr 09 09:33:44 2013 -0700
@@ -25,6 +25,7 @@
 
 package javafx.scene.layout;
 
+import com.sun.javafx.geom.Vec2d;
 import java.util.List;
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.ObjectPropertyBase;
@@ -35,6 +36,7 @@
 import javafx.geometry.Pos;
 import javafx.geometry.VPos;
 import javafx.scene.Node;
+import static javafx.scene.layout.Region.positionInArea;
 
 
 /**
@@ -531,9 +533,8 @@
         final Node t = getTop();
 
         double topHeight = 0;
-        Insets topMargin = null;
         if (t != null && t.isManaged()) {
-            topMargin = getNodeMargin(t);
+            Insets topMargin = getNodeMargin(t);
             if (getContentBias() == Orientation.VERTICAL) {
                 topHeight = heights[0] == -1 ? t.prefHeight(-1) : heights[0];
             } else {
@@ -541,12 +542,21 @@
                         t.prefHeight(insideWidth - topMargin.getLeft() - topMargin.getRight()) +
                         topMargin.getBottom());
             }
+            topHeight = Math.min(topHeight, insideHeight);
+            Vec2d result = boundedNodeSizeWithBias(t, adjustWidthByMargin(insideWidth, topMargin),
+                    adjustHeightByMargin(topHeight, topMargin), true, true, TEMP_VEC2D);
+            topHeight = snapSize(result.y);
+            t.resize(snapSize(result.x), topHeight);
+            Pos alignment = getAlignment(t);
+            positionInArea(t, insideX, insideY, insideWidth, topHeight, 0/*ignore baseline*/,
+                    topMargin,
+                    alignment != null? alignment.getHpos() : HPos.LEFT,
+                    alignment != null? alignment.getVpos() : VPos.TOP, isSnapToPixel());
         }
 
         double bottomHeight = 0;
-        Insets bottomMargin = null;
         if (b != null && b.isManaged()) {
-            bottomMargin = getNodeMargin(b);
+            Insets bottomMargin = getNodeMargin(b);
             if (getContentBias() == Orientation.VERTICAL) {
                 bottomHeight = heights[4] == -1 ? b.prefHeight(-1) : heights[4];
             } else {
@@ -554,12 +564,22 @@
                         b.prefHeight(insideWidth - bottomMargin.getLeft() - bottomMargin.getRight()) +
                         bottomMargin.getBottom());
             }
+            bottomHeight = Math.min(bottomHeight, insideHeight - topHeight);
+            Vec2d result = boundedNodeSizeWithBias(b, adjustWidthByMargin(insideWidth, bottomMargin),
+                    adjustHeightByMargin(bottomHeight, bottomMargin), true, true, TEMP_VEC2D);
+            bottomHeight = snapSize(result.y);
+            b.resize(snapSize(result.x), bottomHeight);
+            Pos alignment = getAlignment(b);
+            positionInArea(b, insideX, insideY + insideHeight - bottomHeight,
+                    insideWidth, bottomHeight, 0/*ignore baseline*/,
+                    bottomMargin,
+                    alignment != null? alignment.getHpos() : HPos.LEFT,
+                    alignment != null? alignment.getVpos() : VPos.BOTTOM, isSnapToPixel());
         }
 
         double leftWidth = 0;
-        Insets leftMargin = null;
         if (l != null && l.isManaged()) {
-            leftMargin = getNodeMargin(l);
+            Insets leftMargin = getNodeMargin(l);
             if (getContentBias() == Orientation.HORIZONTAL) {
                 leftWidth =  widths[0] == -1 ? l.prefWidth(-1) : widths[0];
             } else {
@@ -567,12 +587,22 @@
                     l.prefWidth(insideHeight - topHeight - bottomHeight - leftMargin.getTop() - leftMargin.getBottom()) +
                     leftMargin.getRight());
             }
+            leftWidth = Math.min(leftWidth, insideWidth);
+            Vec2d result = boundedNodeSizeWithBias(l, adjustWidthByMargin(leftWidth, leftMargin),
+                    adjustHeightByMargin(insideHeight - topHeight - bottomHeight, leftMargin), true, true, TEMP_VEC2D);
+            leftWidth = snapSize(result.x);
+            l.resize(leftWidth, snapSize(result.y));
+            Pos alignment = getAlignment(l);
+            positionInArea(l, insideX, insideY + topHeight,
+                    leftWidth, insideHeight - topHeight - bottomHeight, 0/*ignore baseline*/,
+                    leftMargin,
+                    alignment != null? alignment.getHpos() : HPos.LEFT,
+                    alignment != null? alignment.getVpos() : VPos.TOP, isSnapToPixel());
         }
 
         double rightWidth = 0;
-        Insets rightMargin = null;
         if (r != null && r.isManaged()) {
-            rightMargin = getNodeMargin(r);
+            Insets rightMargin = getNodeMargin(r);
             if (getContentBias() == Orientation.HORIZONTAL) {
                 rightWidth = widths[2] == -1 ? r.prefWidth(-1) : widths[2];
             } else {
@@ -580,45 +610,17 @@
                         r.prefWidth(insideHeight - topHeight - bottomHeight - rightMargin.getTop() - rightMargin.getBottom()) +
                         rightMargin.getRight());
             }
-        }
-
-        if (t != null && t.isManaged()) {
-            Pos alignment = getAlignment(t);
-            topHeight = Math.min(topHeight, insideHeight);
-            layoutInArea(t, insideX, insideY, insideWidth, topHeight, 0/*ignore baseline*/,
-                    topMargin,
-                    alignment != null? alignment.getHpos() : HPos.LEFT,
-                    alignment != null? alignment.getVpos() : VPos.TOP);
-        }
-
-        if (b != null && b.isManaged() ) {
-            Pos alignment = getAlignment(b);
-            bottomHeight = Math.min(bottomHeight, insideHeight - topHeight);
-            layoutInArea(b, insideX, insideY + insideHeight - bottomHeight,
-                    insideWidth, bottomHeight, 0/*ignore baseline*/,
-                    bottomMargin,
-                    alignment != null? alignment.getHpos() : HPos.LEFT,
-                    alignment != null? alignment.getVpos() : VPos.BOTTOM);
-        }
-
-        if (l != null && l.isManaged()) {
-            Pos alignment = getAlignment(l);
-            leftWidth = Math.min(leftWidth, insideWidth);
-            layoutInArea(l, insideX, insideY + topHeight,
-                    leftWidth, insideHeight - topHeight - bottomHeight, 0/*ignore baseline*/,
-                    leftMargin,
-                    alignment != null? alignment.getHpos() : HPos.LEFT,
-                    alignment != null? alignment.getVpos() : VPos.TOP);
-        }
-
-        if (r != null && r.isManaged()) {
+            rightWidth = Math.min(rightWidth, insideWidth - leftWidth);
+            Vec2d result = boundedNodeSizeWithBias(r, rightWidth,
+                    insideHeight - topHeight - bottomHeight - rightMargin.getTop() - rightMargin.getBottom(), true, true, TEMP_VEC2D);
+            rightWidth = snapSize(result.x);
+            r.resize(rightWidth, snapSize(result.y));
             Pos alignment = getAlignment(r);
-            rightWidth = Math.min(rightWidth, insideWidth - leftWidth);
-            layoutInArea(r, insideX + insideWidth - rightWidth, insideY + topHeight,
+            positionInArea(r, insideX + insideWidth - rightWidth, insideY + topHeight,
                     rightWidth, insideHeight - topHeight - bottomHeight, 0/*ignore baseline*/,
                     rightMargin,
                     alignment != null? alignment.getHpos() : HPos.RIGHT,
-                    alignment != null? alignment.getVpos() : VPos.TOP);
+                    alignment != null? alignment.getVpos() : VPos.TOP, isSnapToPixel());
         }
 
         if (c != null && c.isManaged()) {
--- a/javafx-ui-common/src/javafx/scene/layout/GridPane.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/src/javafx/scene/layout/GridPane.java	Tue Apr 09 09:33:44 2013 -0700
@@ -1190,7 +1190,7 @@
             List<Node> baselineNodes = new ArrayList<Node>();
             for(int j = 0, k = 0, size = startNodes.size(); j < size; j++) {
                 Node n = startNodes.get(j);
-                if (getValignment(n) == VPos.BASELINE) {
+                if (rowVPos == VPos.BASELINE || getValignment(n) == VPos.BASELINE) {
                     baselineNodes.add(n);
                     margins[k++] = getMargin(n);
                 }
--- a/javafx-ui-common/src/javafx/scene/layout/HBox.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/src/javafx/scene/layout/HBox.java	Tue Apr 09 09:33:44 2013 -0700
@@ -255,8 +255,8 @@
                 public void invalidated() {
                     requestLayout();
                 }
-                
-                @Override 
+
+                @Override
                 public CssMetaData getCssMetaData () {
                     return StyleableProperties.SPACING;
                 }
@@ -274,7 +274,7 @@
         }
         return spacing;
     }
-    
+
     private DoubleProperty spacing;
     public final void setSpacing(double value) { spacingProperty().set(value); }
     public final double getSpacing() { return spacing == null ? 0 : spacing.get(); }
@@ -292,8 +292,8 @@
                 public void invalidated() {
                     requestLayout();
                 }
-                
-                @Override 
+
+                @Override
                 public CssMetaData<HBox, Pos> getCssMetaData() {
                     return StyleableProperties.ALIGNMENT;
                 }
@@ -311,7 +311,7 @@
         }
         return alignment;
     }
-    
+
     private ObjectProperty<Pos> alignment;
     public final void setAlignment(Pos value) { alignmentProperty().set(value); }
     public final Pos getAlignment() { return alignment == null ? Pos.TOP_LEFT : alignment.get(); }
@@ -333,7 +333,7 @@
                 public void invalidated() {
                     requestLayout();
                 }
-                                
+
                 @Override
                 public CssMetaData<HBox, Boolean> getCssMetaData() {
                     return StyleableProperties.FILL_HEIGHT;
@@ -352,7 +352,7 @@
         }
         return fillHeight;
     }
-    
+
     private BooleanProperty fillHeight;
     public final void setFillHeight(boolean value) { fillHeightProperty().set(value); }
     public final boolean isFillHeight() { return fillHeight == null ? true : fillHeight.get(); }
@@ -390,9 +390,9 @@
         if (getContentBias() == Orientation.HORIZONTAL) {
             // if width is different than preferred, then child widths may grow or shrink,
             // altering the height of any child with a horizontal contentBias.
-            double minWidths[] = getAreaWidths(managed, -1, true);
-            adjustAreaWidths(managed, minWidths, width, -1);
-            contentHeight = computeMaxMinAreaHeight(managed, getMargins(managed), minWidths, getAlignmentInternal().getVpos());
+            double prefWidths[] = getAreaWidths(managed, -1, false);
+            adjustAreaWidths(managed, prefWidths, width, -1);
+            contentHeight = computeMaxMinAreaHeight(managed, getMargins(managed), prefWidths, getAlignmentInternal().getVpos());
         } else {
             contentHeight = computeMaxMinAreaHeight(managed, getMargins(managed), getAlignmentInternal().getVpos());
         }
@@ -460,7 +460,7 @@
         double extraWidth = (width == -1? prefWidth(-1) : width) -
                 snapSpace(insets.getLeft()) - snapSpace(insets.getRight()) - contentWidth;
 
-        if (extraWidth != 0) {            
+        if (extraWidth != 0) {
             double remaining = growOrShrinkAreaWidths(managed, areaWidths, Priority.ALWAYS, extraWidth,
                     shouldFillHeight() && height != -1? height - top - bottom : -1);
             remaining = growOrShrinkAreaWidths(managed, areaWidths, Priority.SOMETIMES, remaining,
@@ -498,7 +498,7 @@
             for (int i = 0, size = adjusting.size(); i < size; i++) {
                 final Node child = adjusting.get(i);
                 final int childIndex = managed.indexOf(child);
-                final double limit = areaLimitWidths[adjustList.indexOf(child)] - areaWidths[childIndex]; // negative in shrinking case                
+                final double limit = areaLimitWidths[adjustList.indexOf(child)] - areaWidths[childIndex]; // negative in shrinking case
                 final double change = Math.abs(limit) <= Math.abs(portion)? limit : portion;
                 areaWidths[childIndex] += change;
                 //if (node.id.startsWith("debug.")) println("{if (shrinking) "shrink" else "grow"}: {node.id} portion({portion})=available({available})/({sizeof adjusting}) change={change}");
@@ -574,9 +574,9 @@
       */
      private static class StyleableProperties {
 
-         private static final CssMetaData<HBox,Pos> ALIGNMENT = 
+         private static final CssMetaData<HBox,Pos> ALIGNMENT =
              new CssMetaData<HBox,Pos>("-fx-alignment",
-                 new EnumConverter<Pos>(Pos.class), 
+                 new EnumConverter<Pos>(Pos.class),
                  Pos.TOP_LEFT) {
 
             @Override
@@ -588,10 +588,10 @@
             public StyleableProperty<Pos> getStyleableProperty(HBox node) {
                 return (StyleableProperty<Pos>)node.alignmentProperty();
             }
-                     
+
          };
-         
-         private static final CssMetaData<HBox,Boolean> FILL_HEIGHT = 
+
+         private static final CssMetaData<HBox,Boolean> FILL_HEIGHT =
              new CssMetaData<HBox,Boolean>("-fx-fill-height",
                  BooleanConverter.getInstance(), Boolean.TRUE) {
 
@@ -605,10 +605,10 @@
             public StyleableProperty<Boolean> getStyleableProperty(HBox node) {
                 return (StyleableProperty<Boolean>)node.fillHeightProperty();
             }
-                     
+
          };
-         
-         private static final CssMetaData<HBox,Number> SPACING = 
+
+         private static final CssMetaData<HBox,Number> SPACING =
              new CssMetaData<HBox,Number>("-fx-spacing",
                  SizeConverter.getInstance(), 0.0){
 
@@ -621,7 +621,7 @@
             public StyleableProperty<Number> getStyleableProperty(HBox node) {
                 return (StyleableProperty<Number>)node.spacingProperty();
             }
-                     
+
          };
 
          private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
@@ -647,8 +647,8 @@
      * {@inheritDoc}
      *
      */
-    
-    
+
+
     @Override
     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
         return getClassCssMetaData();
--- a/javafx-ui-common/src/javafx/scene/layout/Region.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/src/javafx/scene/layout/Region.java	Tue Apr 09 09:33:44 2013 -0700
@@ -61,6 +61,7 @@
 import com.sun.javafx.css.converters.SizeConverter;
 import com.sun.javafx.geom.BaseBounds;
 import com.sun.javafx.geom.PickRay;
+import com.sun.javafx.geom.Vec2d;
 import com.sun.javafx.geom.transform.BaseTransform;
 import com.sun.javafx.scene.DirtyBits;
 import com.sun.javafx.scene.input.PickResultChooser;
@@ -77,7 +78,7 @@
  * Region is the base class for all JavaFX Node-based UI Controls, and all layout containers.
  * It is a resizable Parent node which can be styled from CSS. It can have multiple backgrounds
  * and borders. It is designed to support as much of the CSS3 specification for backgrounds
- * and borders as is relevant to JavaFX. 
+ * and borders as is relevant to JavaFX.
  * The full specification is available at <a href="http://www.w3.org/TR/2012/CR-css3-background-20120724/">the W3C</a>.
  * <p/>
  * Every Region has its layout bounds, which are specified to be (0, 0, width, height). A Region might draw outside
@@ -159,6 +160,8 @@
      */
     public static final double USE_COMPUTED_SIZE = -1;
 
+    static Vec2d TEMP_VEC2D = new Vec2d();
+
     /***************************************************************************
      *                                                                         *
      * Static convenience methods for layout                                   *
@@ -192,6 +195,22 @@
         return a <= b ? a : b;
     }
 
+    double adjustWidthByMargin(double width, Insets margin) {
+        if (margin == null || margin == Insets.EMPTY) {
+            return width;
+        }
+        boolean isSnapToPixel = isSnapToPixel();
+        return width - snapSpace(margin.getLeft(), isSnapToPixel) - snapSpace(margin.getRight(), isSnapToPixel);
+    }
+
+    double adjustHeightByMargin(double height, Insets margin) {
+        if (margin == null || margin == Insets.EMPTY) {
+            return height;
+        }
+        boolean isSnapToPixel = isSnapToPixel();
+        return height - snapSpace(margin.getTop(), isSnapToPixel) - snapSpace(margin.getBottom(), isSnapToPixel);
+    }
+
     /**
      * If snapToPixel is true, then the value is rounded using Math.round. Otherwise,
      * the value is simply returned. This method will surely be JIT'd under normal
@@ -294,7 +313,7 @@
      * Constructors                                                            *
      *                                                                         *
      **************************************************************************/
-    
+
     /**
      * Creates a new Region with an empty Background and and empty Border. The
      * Region defaults to having pickOnBounds set to true, meaning that any pick
@@ -715,7 +734,7 @@
     private final class MinPrefMaxProperty extends StyleableDoubleProperty {
         private final String name;
         private final CssMetaData<? extends Styleable, Number> cssMetaData;
-        
+
         MinPrefMaxProperty(String name, double initialValue, CssMetaData<? extends Styleable, Number> cssMetaData) {
             super(initialValue);
             this.name = name;
@@ -1382,7 +1401,7 @@
             alt = snapSize(boundedSize(
                     child.minHeight(-1), height != -1? height - top - bottom :
                            child.prefHeight(-1), child.maxHeight(-1)));
-        }        
+        }
         return left + snapSize(boundedSize(child.minWidth(alt), child.prefWidth(alt), child.maxWidth(alt))) + right;
     }
 
@@ -1401,7 +1420,7 @@
             alt = snapSize(boundedSize(
                     child.minWidth(-1), width != -1? width - left - right :
                            child.prefWidth(-1), child.maxWidth(-1)));
-        }        
+        }
         return top + snapSize(boundedSize(child.minHeight(alt), child.prefHeight(alt), child.maxHeight(alt))) + bottom;
     }
 
@@ -1423,7 +1442,7 @@
         return left + snapSize(boundedSize(child.minWidth(alt), max, child.maxWidth(alt))) + right;
     }
 
-    double computeChildMaxAreaHeight(Node child, Insets margin, double width) {
+     double computeChildMaxAreaHeight(Node child, Insets margin, double width) {
         double max = child.maxHeight(-1);
         if (max == Double.MAX_VALUE) {
             return max;
@@ -1472,7 +1491,7 @@
 
     /* Max of children's pref area widths */
 
-    double computeMaxPrefAreaWidth(List<Node>children, Insets margins[], HPos halignment /* ignored for now */) {        
+    double computeMaxPrefAreaWidth(List<Node>children, Insets margins[], HPos halignment /* ignored for now */) {
         return getMaxAreaWidth(children, margins, new double[] { -1 }, false);
     }
 
@@ -1498,6 +1517,64 @@
         return getMaxAreaHeight(children, childMargins, childWidths, valignment, false);
     }
 
+    /**
+     * Returns the size of a Node that should be placed in an area of the specified size,
+     * bounded in it's min/max size, respecting bias.
+     *
+     * @param node the node
+     * @param areaWidth the width of the bounding area where the node is going to be placed
+     * @param areaHeight the height of the bounding area where the node is going to be placed
+     * @param fillWidth if Node should try to fill the area width
+     * @param fillHeight if Node should try to fill the area height
+     * @param result Vec2d object for the result or null if new one should be created
+     * @return Vec2d object with width(x parameter) and height (y parameter)
+     */
+    static Vec2d boundedNodeSizeWithBias(Node node, double areaWidth, double areaHeight,
+            boolean fillWidth, boolean fillHeight, Vec2d result) {
+        if (result == null) {
+            result = new Vec2d();
+        }
+
+        Orientation bias = node.getContentBias();
+
+        double childWidth = 0;
+        double childHeight = 0;
+
+        if (bias == null) {
+            childWidth = boundedSize(
+                    node.minWidth(-1), fillWidth ? areaWidth
+                    : Math.min(areaWidth, node.prefWidth(-1)),
+                    node.maxWidth(-1));
+            childHeight = boundedSize(
+                    node.minHeight(-1), fillHeight ? areaHeight
+                    : Math.min(areaHeight, node.prefHeight(-1)),
+                    node.maxHeight(-1));
+
+        } else if (bias == Orientation.HORIZONTAL) {
+            childWidth = boundedSize(
+                    node.minWidth(-1), fillWidth ? areaWidth
+                    : Math.min(areaWidth, node.prefWidth(-1)),
+                    node.maxWidth(-1));
+            childHeight = boundedSize(
+                    node.minHeight(childWidth), fillHeight ? areaHeight
+                    : Math.min(areaHeight, node.prefHeight(childWidth)),
+                    node.maxHeight(childWidth));
+
+        } else { // bias == VERTICAL
+            childHeight = boundedSize(
+                    node.minHeight(-1), fillHeight ? areaHeight
+                    : Math.min(areaHeight, node.prefHeight(-1)),
+                    node.maxHeight(-1));
+            childWidth = boundedSize(
+                    node.minWidth(childHeight), fillWidth ? areaWidth
+                    : Math.min(areaWidth, node.prefWidth(childHeight)),
+                    node.maxWidth(childHeight));
+        }
+
+        result.set(childWidth, childHeight);
+        return result;
+    }
+
     /* utility method for computing the max of children's min or pref heights, taking into account baseline alignment */
     private double getMaxAreaHeight(List<Node> children, Insets childMargins[],  double childWidths[], VPos valignment, boolean minimum) {
         final double lastChildWidth = childWidths.length > 0 ? childWidths[childWidths.length - 1] : 0;
@@ -1608,9 +1685,9 @@
         Insets childMargin = margin != null? margin : Insets.EMPTY;
 
         position(child, areaX, areaY, areaWidth, areaHeight, areaBaselineOffset,
-                snapSpace(childMargin.getTop(), isSnapToPixel), 
+                snapSpace(childMargin.getTop(), isSnapToPixel),
                 snapSpace(childMargin.getRight(), isSnapToPixel),
-                snapSpace(childMargin.getBottom(), isSnapToPixel), 
+                snapSpace(childMargin.getBottom(), isSnapToPixel),
                 snapSpace(childMargin.getLeft(), isSnapToPixel),
                 halignment, valignment, isSnapToPixel);
     }
@@ -1780,58 +1857,23 @@
                                HPos halignment, VPos valignment) {
         layoutInArea(child, areaX, areaY, areaWidth, areaHeight, areaBaselineOffset, margin, fillWidth, fillHeight, halignment, valignment, isSnapToPixel());
     }
-    
+
     public static void layoutInArea(Node child, double areaX, double areaY,
                                double areaWidth, double areaHeight,
                                double areaBaselineOffset,
                                Insets margin, boolean fillWidth, boolean fillHeight,
                                HPos halignment, VPos valignment, boolean isSnapToPixel) {
-        
-        Insets childMargin = margin != null? margin : Insets.EMPTY;
+
+        Insets childMargin = margin != null ? margin : Insets.EMPTY;
         double top = snapSpace(childMargin.getTop(), isSnapToPixel);
         double bottom = snapSpace(childMargin.getBottom(), isSnapToPixel);
         double left = snapSpace(childMargin.getLeft(), isSnapToPixel);
         double right = snapSpace(childMargin.getRight(), isSnapToPixel);
+
         if (child.isResizable()) {
-            Orientation bias = child.getContentBias();
-
-            double innerAreaWidth = areaWidth - left - right;
-            double innerAreaHeight = areaHeight - top - bottom;
-
-            double childWidth = 0;
-            double childHeight = 0;
-
-            if (bias == null) {
-                childWidth = boundedSize(
-                        child.minWidth(-1), fillWidth? innerAreaWidth :
-                                         Math.min(innerAreaWidth,child.prefWidth(-1)),
-                        child.maxWidth(-1));
-                childHeight = boundedSize(
-                        child.minHeight(-1), fillHeight? innerAreaHeight :
-                                         Math.min(innerAreaHeight,child.prefHeight(-1)),
-                        child.maxHeight(-1));
-
-            } else if (bias == Orientation.HORIZONTAL) {
-                childWidth = boundedSize(
-                        child.minWidth(-1), fillWidth? innerAreaWidth :
-                                         Math.min(innerAreaWidth,child.prefWidth(-1)),
-                        child.maxWidth(-1));
-                childHeight = boundedSize(
-                        child.minHeight(childWidth), fillHeight? innerAreaHeight :
-                                         Math.min(innerAreaHeight,child.prefHeight(childWidth)),
-                        child.maxHeight(childWidth));
-
-            } else { // bias == VERTICAL
-                childHeight = boundedSize(
-                        child.minHeight(-1), fillHeight? innerAreaHeight :
-                                         Math.min(innerAreaHeight,child.prefHeight(-1)),
-                        child.maxHeight(-1));
-                childWidth = boundedSize(
-                        child.minWidth(childHeight), fillWidth? innerAreaWidth :
-                                         Math.min(innerAreaWidth,child.prefWidth(childHeight)),
-                        child.maxWidth(childHeight));
-            }
-            child.resize(snapSize(childWidth, isSnapToPixel),snapSize(childHeight, isSnapToPixel));
+            Vec2d size = boundedNodeSizeWithBias(child, areaWidth - left - right, areaHeight - top - bottom,
+                    fillWidth, fillHeight, TEMP_VEC2D);
+            child.resize(snapSize(size.x, isSnapToPixel),snapSize(size.y, isSnapToPixel));
         }
         position(child, areaX, areaY, areaWidth, areaHeight, areaBaselineOffset,
                 top, right, bottom, left, halignment, valignment, isSnapToPixel);
@@ -2180,7 +2222,7 @@
     }
 
     private Bounds boundingBox;
-    
+
     /**
      * The layout bounds of this region: {@code 0, 0  width x height}
      *
@@ -2371,7 +2413,7 @@
             }
          };
 
-         private static final CssMetaData<Region, Boolean> SCALE_SHAPE = 
+         private static final CssMetaData<Region, Boolean> SCALE_SHAPE =
              new CssMetaData<Region,Boolean>("-fx-scale-shape",
                  BooleanConverter.getInstance(), Boolean.TRUE){
 
@@ -2384,7 +2426,7 @@
             }
         };
 
-         private static final CssMetaData<Region,Boolean> POSITION_SHAPE = 
+         private static final CssMetaData<Region,Boolean> POSITION_SHAPE =
              new CssMetaData<Region,Boolean>("-fx-position-shape",
                  BooleanConverter.getInstance(), Boolean.TRUE){
 
@@ -2451,7 +2493,7 @@
                 return (StyleableProperty<Number>)node.prefHeightProperty();
             }
         };
-         
+
          private static final CssMetaData<Region, Number> MAX_HEIGHT =
              new CssMetaData<Region,Number>("-fx-max-height",
                  SizeConverter.getInstance(), USE_COMPUTED_SIZE){
@@ -2465,7 +2507,7 @@
                 return (StyleableProperty<Number>)node.maxHeightProperty();
             }
         };
-         
+
          private static final CssMetaData<Region, Number> MIN_WIDTH =
              new CssMetaData<Region,Number>("-fx-min-width",
                  SizeConverter.getInstance(), USE_COMPUTED_SIZE){
@@ -2493,7 +2535,7 @@
                 return (StyleableProperty<Number>)node.prefWidthProperty();
             }
         };
-         
+
          private static final CssMetaData<Region, Number> MAX_WIDTH =
              new CssMetaData<Region,Number>("-fx-max-width",
                  SizeConverter.getInstance(), USE_COMPUTED_SIZE){
@@ -2543,8 +2585,8 @@
      * {@inheritDoc}
      *
      */
-    
-    
+
+
     @Override
     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
         return getClassCssMetaData();
--- a/javafx-ui-common/src/javafx/scene/layout/VBox.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/src/javafx/scene/layout/VBox.java	Tue Apr 09 09:33:44 2013 -0700
@@ -347,7 +347,7 @@
      *
      * @return null unless one of its children has a content bias.
      */
-    @Override public Orientation getContentBias() {        
+    @Override public Orientation getContentBias() {
         final List<Node> children = getChildren();
         for (int i=0, size=children.size(); i<size; i++) {
             Node child = children.get(i);
@@ -363,9 +363,9 @@
         List<Node>managed = getManagedChildren();
         double contentWidth = 0;
         if (getContentBias() == Orientation.VERTICAL) {
-            double minHeights[] = getAreaHeights(managed, -1, true);
-            adjustAreaHeights(managed, minHeights, height, -1);
-            contentWidth = computeMaxMinAreaWidth(managed, getMargins(managed), minHeights, getAlignmentInternal().getHpos());
+            double prefHeights[] = getAreaHeights(managed, -1, false);
+            adjustAreaHeights(managed, prefHeights, height, -1);
+            contentWidth = computeMaxMinAreaWidth(managed, getMargins(managed), prefHeights, getAlignmentInternal().getHpos());
         } else {
             contentWidth = computeMaxMinAreaWidth(managed, getMargins(managed), getAlignmentInternal().getHpos());
         }
@@ -419,7 +419,7 @@
             prefAreaHeights[i] = minimum?
                                computeChildMinAreaHeight(child, margin,
                                    isFillWidth()? insideWidth : child.minWidth(-1)) :
-                                   computeChildPrefAreaHeight(child, margin, 
+                                   computeChildPrefAreaHeight(child, margin,
                                        isFillWidth()? insideWidth : child.prefWidth(-1));
         }
         return prefAreaHeights;
@@ -428,16 +428,16 @@
     private double adjustAreaHeights(List<Node>managed, double areaHeights[], double height, double width) {
         Insets insets = getInsets();
         double left = snapSpace(insets.getLeft());
-        double right = snapSpace(insets.getRight());        
+        double right = snapSpace(insets.getRight());
 
         double contentHeight = computeContentHeight(areaHeights);
         double extraHeight = (height == -1 ? prefHeight(-1) : height) -
                 snapSpace(insets.getTop()) - snapSpace(insets.getBottom()) - contentHeight;
 
         if (extraHeight != 0) {
-            double remaining = growOrShrinkAreaHeights(managed, areaHeights, 
+            double remaining = growOrShrinkAreaHeights(managed, areaHeights,
                     Priority.ALWAYS, extraHeight, isFillWidth() && width != -1? width - left - right: -1);
-            remaining = growOrShrinkAreaHeights(managed, areaHeights, 
+            remaining = growOrShrinkAreaHeights(managed, areaHeights,
                     Priority.SOMETIMES, remaining, isFillWidth() && width != -1? width - left - right: -1);
             contentHeight += (extraHeight - remaining);
         }
@@ -459,7 +459,7 @@
         }
 
         double[] areaLimitHeights = new double[adjustList.size()];
-        for (int i = 0, size = adjustList.size(); i < size; i++) {        
+        for (int i = 0, size = adjustList.size(); i < size; i++) {
             Node child = adjustList.get(i);
             Insets margin  = getMargin(child);
             areaLimitHeights[i] = shrinking?
@@ -522,7 +522,7 @@
         double y = top + computeYOffset(height - top - bottom, contentHeight, vpos);
 
         for (int i = 0, size = managed.size(); i < size; i++) {
-            Node child = managed.get(i);            
+            Node child = managed.get(i);
             layoutInArea(child, x, y, contentWidth, actualAreaHeights[i],
                        /* baseline shouldn't matter */actualAreaHeights[i],
                        getMargin(child), isFillWidth(), true,
@@ -530,7 +530,7 @@
             y += actualAreaHeights[i] + space;
         }
     }
-    
+
     /***************************************************************************
      *                                                                         *
      *                         Stylesheet Handling                             *
@@ -542,7 +542,7 @@
       * @treatAsPrivate implementation detail
       */
      private static class StyleableProperties {
-         private static final CssMetaData<VBox,Pos> ALIGNMENT = 
+         private static final CssMetaData<VBox,Pos> ALIGNMENT =
              new CssMetaData<VBox,Pos>("-fx-alignment",
                  new EnumConverter<Pos>(Pos.class), Pos.TOP_LEFT){
 
@@ -556,8 +556,8 @@
                 return (StyleableProperty<Pos>)node.alignmentProperty();
             }
         };
-         
-         private static final CssMetaData<VBox,Boolean> FILL_WIDTH = 
+
+         private static final CssMetaData<VBox,Boolean> FILL_WIDTH =
              new CssMetaData<VBox,Boolean>("-fx-fill-width",
                  BooleanConverter.getInstance(), Boolean.TRUE) {
 
@@ -571,8 +571,8 @@
                 return (StyleableProperty<Boolean>)node.fillWidthProperty();
             }
         };
-         
-         private static final CssMetaData<VBox,Number> SPACING = 
+
+         private static final CssMetaData<VBox,Number> SPACING =
              new CssMetaData<VBox,Number>("-fx-spacing",
                  SizeConverter.getInstance(), 0d) {
 
@@ -589,7 +589,7 @@
 
          private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
          static {
-            final List<CssMetaData<? extends Styleable, ?>> styleables = 
+            final List<CssMetaData<? extends Styleable, ?>> styleables =
                 new ArrayList<CssMetaData<? extends Styleable, ?>>(Region.getClassCssMetaData());
             styleables.add(ALIGNMENT);
             styleables.add(FILL_WIDTH);
@@ -610,8 +610,8 @@
      * {@inheritDoc}
      *
      */
-    
-    
+
+
     @Override
     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
         return getClassCssMetaData();
--- a/javafx-ui-common/test/unit/com/sun/javafx/test/NodeOrientationTestBase.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/test/unit/com/sun/javafx/test/NodeOrientationTestBase.java	Tue Apr 09 09:33:44 2013 -0700
@@ -31,6 +31,7 @@
 import javafx.scene.Node;
 import javafx.scene.Parent;
 import javafx.scene.Scene;
+import javafx.scene.SubScene;
 
 public abstract class NodeOrientationTestBase {
     protected NodeOrientationTestBase() {
@@ -59,6 +60,12 @@
         return autGroup(NodeOrientation.INHERIT, childNodes);
     }
 
+    protected static SubScene inhSubScene(final Parent rootNode) {
+        final SubScene subScene = new SubScene(rootNode, 400, 300);
+        subScene.setNodeOrientation(NodeOrientation.INHERIT);
+        return subScene;
+    }
+
     protected static Group ltrManGroup(final Node... childNodes) {
         return manGroup(NodeOrientation.LEFT_TO_RIGHT, childNodes);
     }
@@ -139,6 +146,10 @@
                 nextIndex = updateOrientation(childNode, updateString,
                                               nextIndex);
             }
+        } else if (node instanceof SubScene) {
+            final Node nextRoot = ((SubScene) node).getRoot();
+            nextIndex = updateOrientation(nextRoot, updateString,
+                                          nextIndex);
         }
 
         return nextIndex;
@@ -179,6 +190,9 @@
             for (final Node childNode: childNodes) {
                 collectState(dest, childNode, encoder);
             }
+        } else if (node instanceof SubScene) {
+            final Node nextRoot = ((SubScene) node).getRoot();
+            collectState(dest, nextRoot, encoder);
         }
     }
 }
--- a/javafx-ui-common/test/unit/javafx/scene/Node_effectiveOrientation_Test.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/test/unit/javafx/scene/Node_effectiveOrientation_Test.java	Tue Apr 09 09:33:44 2013 -0700
@@ -51,6 +51,15 @@
                                    inhAutGroup())))));
     }
 
+    private static Scene lriiliWithSubSceneScene() {
+        return ltrScene(
+                   rtlAutGroup(
+                       inhSubScene(
+                           inhAutGroup(
+                               ltrAutGroup(
+                                   inhAutGroup())))));
+    }
+
     private static Scene liirliPrecachedScene() {
         final Scene scene =
                 ltrScene(
@@ -103,6 +112,15 @@
                         { lriiliScene(), "....I.", "LRRRRR" },
                         { lriiliScene(), "RIIIII", "RRRRRR" },
 
+                        {
+                            lriiliWithSubSceneScene(),
+                            ".......", "LRRRLL"
+                        },
+                        {
+                            lriiliWithSubSceneScene(),
+                            ".L.....", "LLLLLL"
+                        },
+
                         { liirliPrecachedScene(), "......", "LLLRLL" },
                         { liirliPrecachedScene(), "R.....", "RRRRLL" },
                         { liirliPrecachedScene(), "...I..", "LLLLLL" },
--- a/javafx-ui-common/test/unit/javafx/scene/Node_hasMirroring_Test.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/test/unit/javafx/scene/Node_hasMirroring_Test.java	Tue Apr 09 09:33:44 2013 -0700
@@ -49,6 +49,16 @@
                                    inhAutGroup())))));
     }
 
+    private static Scene lriiliWithSubSceneScene() {
+        return ltrScene(
+                   rtlAutGroup(
+                       inhSubScene(
+                           inhAutGroup(
+                               ltrAutGroup(
+                                   inhAutGroup())))));
+    }
+
+
     private static Scene lrIiliScene() {
         return ltrScene(
                    rtlAutGroup(
@@ -89,6 +99,11 @@
                         { lriiliScene(), "....I.", ".M...." }, // LRRRRR
                         { lriiliScene(), "RIIIII", ".M...." }, // RRRRRR
 
+                        {
+                            lriiliWithSubSceneScene(),
+                            "......", ".M..M."
+                        },
+
                         /* effective: LRRRLL, automatic: LRLLLL */
                         { lrIiliScene(), "......", ".MM..." },
                         /* effective: LRLRLR, automatic: LRLLLR */
--- a/javafx-ui-common/test/unit/javafx/scene/layout/BorderPaneTest.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/test/unit/javafx/scene/layout/BorderPaneTest.java	Tue Apr 09 09:33:44 2013 -0700
@@ -28,7 +28,6 @@
 import static org.junit.Assert.*;
 import javafx.geometry.Orientation;
 import org.junit.Before;
-import org.junit.Ignore;
 
 import org.junit.Test;
 
@@ -250,7 +249,6 @@
         assertEquals(200, left.getHeight(), 1e-100);
     }
 
-  //  @Ignore
     @Test public void testChildrenInAllPositions() {
         MockResizable center = new MockResizable(10,20, 100,200, 1000,1000);
         borderpane.setCenter(center);
@@ -282,8 +280,6 @@
         assertEquals(Double.MAX_VALUE, borderpane.maxWidth(-1), 1e-100);
         assertEquals(Double.MAX_VALUE, borderpane.maxHeight(-1), 1e-100);
 
-// TODO Amy: re-enable the following tests once they all pass
-
         borderpane.autosize();
         borderpane.layout();
         assertEquals(0, top.getLayoutX(), 1e-100);
@@ -345,10 +341,15 @@
         assertEquals(19, left.getWidth(), 1e-100);
         assertEquals(217, left.getHeight(), 1e-100);
 
-        assertEquals(40, center.getLayoutX(), 1e-100);
-        assertEquals(5, center.getLayoutY(), 1e-100);
-        assertEquals(180, center.getWidth(), 1e-100);
-        assertEquals(223, center.getHeight(), 1e-100);
+        // Center is HORIZONTALLY biased, so when width is stretched, height is lower
+        double centerWidth = 280 - 19 - 56;
+        double centerHeight = Math.ceil(200 * 200 / centerWidth);
+
+        assertEquals(19, center.getLayoutX(), 1e-100);
+        // center alignment, Math.round == snapPosition
+        assertEquals(Math.round(8 + (240 - 8 - 15 - centerHeight) / 2), center.getLayoutY(), 1e-100);
+        assertEquals(centerWidth, center.getWidth(), 1e-100);
+        assertEquals(centerHeight, center.getHeight(), 1e-100);
 
         assertEquals(224, right.getLayoutX(), 1e-100);
         assertEquals(8, right.getLayoutY(), 1e-100);
--- a/javafx-ui-common/test/unit/javafx/scene/layout/GridPaneTest.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/test/unit/javafx/scene/layout/GridPaneTest.java	Tue Apr 09 09:33:44 2013 -0700
@@ -2344,5 +2344,29 @@
 
         assertEquals(76, cw[0], 1e-100);
         assertEquals(75, cw[1], 1e-100);
-    }    
+    }
+
+    @Test public void testBaselineRowAlignment() {
+        MockResizable child1 = new MockResizable(50,50, 200,200, 300,300); //baseline = 190
+        MockResizable child2 = new MockResizable(100,100, 300,300, 500,500); //baseline = 290
+        gridpane.add(child1, 0, 0);
+        gridpane.add(child2, 1, 0);
+
+        RowConstraints rc = new RowConstraints();
+        rc.setValignment(VPos.BASELINE);
+        gridpane.getRowConstraints().addAll(rc);
+
+        gridpane.autosize();
+        gridpane.layout();
+
+        assertEquals(0, child1.getLayoutX(), 1e-100);
+        assertEquals(100, child1.getLayoutY(), 1e-100);
+        assertEquals(200, child1.getLayoutBounds().getWidth(), 1e-100);
+        assertEquals(200, child1.getLayoutBounds().getHeight(), 1e-100);
+
+        assertEquals(200, child2.getLayoutX(), 1e-100);
+        assertEquals(0, child2.getLayoutY(), 1e-100);
+        assertEquals(300, child2.getLayoutBounds().getWidth(), 1e-100);
+        assertEquals(300, child2.getLayoutBounds().getHeight(), 1e-100);
+    }
 }
--- a/javafx-ui-common/test/unit/javafx/scene/layout/HBoxTest.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/test/unit/javafx/scene/layout/HBoxTest.java	Tue Apr 09 09:33:44 2013 -0700
@@ -527,7 +527,7 @@
         assertEquals(250, resizable3.getLayoutX(), 1e-100);
         assertEquals(0, resizable3.getLayoutY(), 1e-100);
     }
-    
+
     @Test public void testHBoxWithHorizontalContentBiasWithHorizontalGrowingFillHeightFalse() {
         hbox.setFillHeight(false);
 
@@ -733,6 +733,9 @@
 
         assertEquals(300, hbox.prefWidth(-1), 1e-100);
         assertEquals(200, hbox.prefHeight(-1), 1e-100);
+        assertEquals(20, hbox.minWidth(-1), 1e-100); //MockBias minWidth == 10
+        assertEquals(200, hbox.minHeight(-1), 1e-100);
+        assertEquals(Math.ceil(Math.max(100 * 100 / 50.0, 200 * 200 / 150.0)), hbox.minHeight(200), 1e-100);
         System.out.println("************************************");
 
         hbox.autosize();
--- a/javafx-ui-common/test/unit/javafx/scene/layout/VBoxTest.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-common/test/unit/javafx/scene/layout/VBoxTest.java	Tue Apr 09 09:33:44 2013 -0700
@@ -342,7 +342,7 @@
         MockResizable child = new MockResizable(100,100);
         vbox.getChildren().addAll(r, biased, child);
 
-        assertEquals(Orientation.HORIZONTAL, vbox.getContentBias());        
+        assertEquals(Orientation.HORIZONTAL, vbox.getContentBias());
     }
 
     @Test public void testVBoxWithHorizontalContentBiasAtPrefSize() {
@@ -377,7 +377,7 @@
         MockResizable resizable = new MockResizable(100,100);
         vbox.getChildren().addAll(rect, biased, resizable);
 
-        assertEquals(Orientation.HORIZONTAL, vbox.getContentBias());        
+        assertEquals(Orientation.HORIZONTAL, vbox.getContentBias());
         assertEquals(600, vbox.prefHeight(50), 0);
 
         vbox.resize(50, 600);
@@ -489,7 +489,7 @@
         vbox.getChildren().addAll(rect, biased, resizable);
 
         vbox.setVgrow(biased, Priority.ALWAYS);
-        
+
         assertEquals(Orientation.VERTICAL, vbox.getContentBias());
         assertEquals(100, vbox.prefWidth(500), 0);
 
@@ -590,12 +590,12 @@
 //        assertEquals(200, vbox.prefWidth(-1), 0);
 //        assertEquals(200, vbox.prefWidth(200), 0);
 //    }
-    
+
     @Test public void testVBoxSetMarginConstraint() {
         MockResizable child1 = new MockResizable(100,200, 300,400, 500,600);
 
         assertNull(VBox.getMargin(child1));
-        
+
         Insets margin = new Insets(10,20,30,40);
         VBox.setMargin(child1, margin);
         assertEquals(margin, VBox.getMargin(child1));
@@ -723,6 +723,9 @@
 
         assertEquals(200, vbox.prefWidth(-1), 1e-100);
         assertEquals(300, vbox.prefHeight(-1), 1e-100);
+        assertEquals(200, vbox.minWidth(-1), 1e-100); //MockBias minWidth == 10
+        assertEquals(20, vbox.minHeight(-1), 1e-100);
+        assertEquals(Math.ceil(Math.max(100 * 100 / 50.0, 200 * 200 / 150.0)), vbox.minWidth(200), 1e-100);
 
         vbox.autosize();
         vbox.layout();
--- a/javafx-ui-quantum/src/com/sun/javafx/tk/quantum/PresentingPainter.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-quantum/src/com/sun/javafx/tk/quantum/PresentingPainter.java	Tue Apr 09 09:33:44 2013 -0700
@@ -27,6 +27,8 @@
 
 import com.sun.prism.Graphics;
 import com.sun.prism.impl.Disposer;
+import com.sun.prism.impl.ManagedResource;
+import com.sun.prism.impl.PrismSettings;
 
 /**
  * The PresentingPainter is used when we are rendering to the main screen.
@@ -64,6 +66,9 @@
             }
 
             boolean needsReset = (presentable == null) || (penWidth != viewWidth) || (penHeight != viewHeight);
+            if (!needsReset && presentable.lockResources()) {
+                needsReset=true;
+            }
             if (needsReset) {
                 if (presentable == null || presentable.recreateOnResize()) {
                     context = factory.createRenderingContext(viewState);
@@ -121,6 +126,11 @@
 
             ViewScene viewScene = (ViewScene)viewState.getScene();
             viewScene.setPainting(false);
+            if (PrismSettings.poolStats ||
+                ManagedResource.anyLockedResources())
+            {
+                ManagedResource.printSummary();
+            }
             renderLock.unlock();
         }
     }
--- a/javafx-ui-quantum/src/com/sun/javafx/tk/quantum/PrismImageLoader2.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-quantum/src/com/sun/javafx/tk/quantum/PrismImageLoader2.java	Tue Apr 09 09:33:44 2013 -0700
@@ -38,6 +38,17 @@
 import com.sun.javafx.tk.PlatformImage;
 import com.sun.prism.Image;
 import com.sun.prism.impl.PrismSettings;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
 class PrismImageLoader2 implements com.sun.javafx.tk.ImageLoader {
 
@@ -177,9 +188,14 @@
         }
     }
 
-    static class AsyncImageLoader
+    static final class AsyncImageLoader
         extends AbstractRemoteResource<PrismImageLoader2>
     {
+        private static final ExecutorService BG_LOADING_EXECUTOR =
+                createExecutor();
+
+        private final AccessControlContext acc;
+
         int width, height;
         boolean preserveRatio;
         boolean smooth;
@@ -194,10 +210,79 @@
             this.height = height;
             this.preserveRatio = preserveRatio;
             this.smooth = smooth;
+            this.acc = AccessController.getContext();
         }
 
+        @Override
         protected PrismImageLoader2 processStream(InputStream stream) throws IOException {
             return new PrismImageLoader2(stream, width, height, preserveRatio, smooth);
         }
+
+        @Override
+        public PrismImageLoader2 call() throws IOException {
+            try {
+                return AccessController.doPrivileged(
+                        new PrivilegedExceptionAction<PrismImageLoader2>() {
+                            @Override
+                            public PrismImageLoader2 run() throws IOException {
+                                return AsyncImageLoader.super.call();
+                            }
+                        }, acc);
+            } catch (final PrivilegedActionException e) {
+                final Throwable cause = e.getCause();
+
+                if (cause instanceof IOException) {
+                    throw (IOException) cause;
+                }
+
+                throw new UndeclaredThrowableException(cause);
+            }
+        }
+
+        @Override
+        public void start() {
+            BG_LOADING_EXECUTOR.execute(future);
+        }
+
+        private static ExecutorService createExecutor() {
+            final ThreadGroup bgLoadingThreadGroup =
+                    AccessController.doPrivileged(
+                        new PrivilegedAction<ThreadGroup>() {
+                            @Override
+                            public ThreadGroup run() {
+                                return new ThreadGroup(
+                                    QuantumToolkit.getFxUserThread()
+                                                  .getThreadGroup(),
+                                    "Background image loading thread pool");
+                            }
+                        });
+
+            final ThreadFactory bgLoadingThreadFactory =
+                    new ThreadFactory() {
+                        @Override
+                        public Thread newThread(final Runnable runnable) {
+                            return AccessController.doPrivileged(
+                                new PrivilegedAction<Thread>() {
+                                    @Override
+                                    public Thread run() {
+                                        final Thread newThread =
+                                                new Thread(bgLoadingThreadGroup,
+                                                           runnable);
+                                        newThread.setPriority(
+                                                      Thread.MIN_PRIORITY);
+
+                                        return newThread;
+                                    }
+                                });
+                        }
+                    };
+
+            final ExecutorService bgLoadingExecutor =
+                    Executors.newCachedThreadPool(bgLoadingThreadFactory);
+            ((ThreadPoolExecutor) bgLoadingExecutor).setKeepAliveTime(
+                                                         1, TimeUnit.SECONDS);
+
+            return bgLoadingExecutor;
+        }
     }
 }
--- a/javafx-ui-quantum/src/com/sun/javafx/tk/quantum/QuantumToolkit.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-quantum/src/com/sun/javafx/tk/quantum/QuantumToolkit.java	Tue Apr 09 09:33:44 2013 -0700
@@ -1393,6 +1393,12 @@
         RTTexture getRT(int w, int h, ResourceFactory rfNew) {
             boolean rttOk = rt != null && rf == rfNew &&
                     rt.getContentWidth() == w && rt.getContentHeight() == h;
+            if (rttOk) {
+                rt.lock();
+                if (rt.isSurfaceLost()) {
+                    rttOk = false;
+                }
+            }
 
             if (!rttOk) {
                 if (rt != null) {
@@ -1562,6 +1568,8 @@
                         }
                     }
 
+                    rt.unlock();
+
                     params.platformImage = pImage;
 
                 } catch (Throwable t) {
@@ -1622,30 +1630,10 @@
                             ? CommonDialogs.Type.SAVE
                             : CommonDialogs.Type.OPEN,
                     (fileChooserType == FileChooserType.OPEN_MULTIPLE),
-                    convertExtensionFilters(extensionFilters));
+                    convertExtensionFilters(extensionFilters),
+                    0);
 
-            String extension = result.getExtensionFilter() == null ?
-                null : result.getExtensionFilter().getExtensions().get(0);
-
-            if (fileChooserType == FileChooserType.OPEN || extension == null || extension.endsWith("*")) {
-                return result.getFiles();
-            } else {
-                final List<File> list = new ArrayList<File>(result.getFiles().size());
-                if (extension.startsWith("*")) {
-                    extension = extension.substring(1, extension.length());
-                }
-
-                for (File f : result.getFiles()) {
-                    String filename = f.getAbsolutePath();
-
-                    if (filename.endsWith(extension)) {
-                        list.add(f);
-                    } else {
-                        list.add(new File(filename + extension));
-                    }
-                }
-                return list;
-            }
+            return result.getFiles();
         } finally {
             if (blockedStage != null) {
                 blockedStage.setEnabled(true);
--- a/javafx-ui-quantum/src/com/sun/javafx/tk/quantum/UploadingPainter.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/javafx-ui-quantum/src/com/sun/javafx/tk/quantum/UploadingPainter.java	Tue Apr 09 09:33:44 2013 -0700
@@ -35,6 +35,8 @@
 import com.sun.prism.Texture.WrapMode;
 import com.sun.prism.impl.BufferUtil;
 import com.sun.prism.impl.Disposer;
+import com.sun.prism.impl.ManagedResource;
+import com.sun.prism.impl.PrismSettings;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -87,7 +89,15 @@
             }
 
             boolean needsReset = (rttexture == null) || (viewWidth != penWidth) || (viewHeight != penHeight);
-            
+
+            if (!needsReset) {
+                rttexture.lock();
+                if (rttexture.isSurfaceLost()) {
+                    rttexture.unlock();
+                    needsReset = true;
+                }
+            }
+
             if (needsReset) {
                 context = factory.createRenderingContext(null);
             }
@@ -138,7 +148,11 @@
                     }
                 }
             }
-            
+
+            if (rttexture != null) {
+                rttexture.unlock();
+            }
+
             if (pix != null) {
                 /* transparent pixels created and ready for upload */
                 // Copy references, which are volatile, used by upload. Thus
@@ -169,6 +183,11 @@
 
             ViewScene viewScene = (ViewScene)viewState.getScene();
             viewScene.setPainting(false);
+            if (PrismSettings.poolStats ||
+                ManagedResource.anyLockedResources())
+            {
+                ManagedResource.printSummary();
+            }
             renderLock.unlock();
         }
     }
--- a/mac.gradle	Thu Apr 04 20:11:19 2013 -0700
+++ b/mac.gradle	Tue Apr 09 09:33:44 2013 -0700
@@ -56,4 +56,5 @@
         "-I$JDK_HOME/include",
         "-I$JDK_HOME/include/darwin",
         commonParams,
-        IS_DEBUG ? "-DDEBUG" : ["-O3", "-ffast-math", "-DNDEBUG"]].flatten()
+        IS_DEBUG ? "-DDEBUG" : ["-O3", "-DNDEBUG"]].flatten()
+        //IS_DEBUG ? "-DDEBUG" : ["-O3", "-ffast-math", "-DNDEBUG"]].flatten()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prism-common-native/Android.mk	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,44 @@
+ #
+ # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ #
+ # This code is free software; you can redistribute it and/or modify it
+ # under the terms of the GNU General Public License version 2 only, as
+ # published by the Free Software Foundation.  Oracle designates this
+ # particular file as subject to the "Classpath" exception as provided
+ # by Oracle in the LICENSE file that accompanied this code.
+ #
+ # This code is distributed in the hope that it will be useful, but WITHOUT
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ # version 2 for more details (a copy is included in the LICENSE file that
+ # accompanied this code).
+ #
+ # You should have received a copy of the GNU General Public License version
+ # 2 along with this work; if not, write to the Free Software Foundation,
+ # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ #
+ # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ # or visit www.oracle.com if you need additional information or have any
+ # questions.
+ #
+
+LOCAL_PATH := $(call my-dir)/src
+include $(CLEAR_VARS)
+
+PRISM_PATH := $(LOCAL_PATH)
+PREFIX := $(PRISM_PATH)/
+
+C_SOURCES := $(wildcard $(PRISM_PATH)/*.c)
+CPP_SOURCES := $(wildcard $(PRISM_PATH)/*.cpp)
+
+LOCAL_MODULE := prism-common
+
+LOCAL_SRC_FILES := $(C_SOURCES:$(PREFIX)%=%)
+LOCAL_SRC_FILES += $(CPP_SOURCES:$(PREFIX)%=%)
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/../build/android
+ 
+LOCAL_CFLAGS += -DANDROID_NDK
+LOCAL_LDLIBS := -llog -ldl
+include $(BUILD_SHARED_LIBRARY)
--- a/prism-common-native/src/NativePiscesRasterizer.c	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common-native/src/NativePiscesRasterizer.c	Tue Apr 09 09:33:44 2013 -0700
@@ -24,7 +24,9 @@
  */
 
 #include <jni.h>
-
+#ifdef ANDROID_NDK
+#include <linux/stddef.h>
+#endif
 #include "com_sun_prism_impl_shape_NativePiscesRasterizer.h"
 
 #include "Renderer.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prism-common/build-android.xml	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="prism-common" default="all" basedir=".">
+
+  <import file="../build-defs.xml"/>
+   
+  <target name="jheaders">
+        <echo>Generate jheaders for prism-common</echo>
+        <mkdir dir="${native.build.dir}"/>
+       <javah 
+          destdir="${native.build.dir}" 
+          classpath="${prismcom.classes.dir}:${javac.classpath}" >
+         <class name="com.sun.prism.BasicStroke"/>
+         <class name="com.sun.prism.MeshView"/>
+         <class name="com.sun.prism.PhongMaterial"/>
+         <class name="com.sun.prism.PixelFormat"/>
+         <class name="com.sun.prism.image.CachingCompoundImage"/>
+         <class name="com.sun.prism.image.CompoundImage"/>
+         <class name="com.sun.prism.image.CompoundTexture"/>
+         <class name="com.sun.prism.impl.BufferUtil"/>
+         <class name="com.sun.prism.impl.Disposer"/>
+         <class name="com.sun.prism.impl.FactoryResetException"/>
+         <class name="com.sun.prism.impl.GlyphCache"/>
+         <class name="com.sun.prism.impl.VertexBuffer"/>
+         <class name="com.sun.prism.impl.packrect.RectanglePacker"/>
+         <class name="com.sun.prism.impl.paint.LinearGradientContext"/>
+         <class name="com.sun.prism.impl.paint.MultipleGradientContext"/>
+         <class name="com.sun.prism.impl.paint.RadialGradientContext"/>
+         <class name="com.sun.prism.impl.shape.NativePiscesRasterizer"/>
+         <class name="com.sun.prism.paint.Gradient"/>
+         <class name="com.sun.prism.paint.LinearGradient"/>
+         <class name="com.sun.prism.paint.RadialGradient"/>
+      </javah>
+  </target>            
+
+  <target name="compile-native" depends="jheaders">
+   <exec executable="${ndk.build.cmd}" dir="${cpp.dir}" failonerror="true">
+     <arg line="APP_BUILD_SCRIPT=Android.mk NDK_PROJECT_PATH=. TARGET_PLATFORM=${android.ndk.target}"/>
+   </exec> 
+   <copy todir="${native.dist.dir}" flatten="true">
+       <fileset dir="${cpp.dir}/libs" includes="armeabi/libprism-common.so"/>
+   </copy>
+  </target>
+
+  <target name="clean-native">       
+    <delete dir="${cpp.dir}/libs"/>
+      <delete dir="${cpp.dir}/obj"/>
+      <delete dir="${native.dist.dir}"/>
+      <delete dir="${native.build.dir}"/>
+  </target>
+
+</project>
--- a/prism-common/build-common.xml	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/build-common.xml	Tue Apr 09 09:33:44 2013 -0700
@@ -14,6 +14,9 @@
   <target name="get-libname-macosx" if="isMacOSX">
     <property name="native.lib.file" value="libprism-common${nativelib.suffix.macosx}"/>
   </target>
+  <target name="get-libname-android" if="isAndroid">
+    <property name="native.lib.file" value="libprism-common.so"/>
+  </target>
   <target name="get-libname-linux" if="isLinux">
     <property name="native.lib.file" value="libprism-common.so"/>
   </target>
@@ -23,7 +26,7 @@
   <target name="get-libname-windows" if="isWindows">
     <property name="native.lib.file" value="prism-common.dll"/>
   </target>
-  <target name="get-libname" depends="get-libname-macosx,get-libname-linux,get-libname-solaris,get-libname-windows"/>
+  <target name="get-libname" depends="get-libname-macosx,get-libname-android,get-libname-linux,get-libname-solaris,get-libname-windows"/>
 
   <target name="-local-pre-init" depends="get-libname"/>
 
--- a/prism-common/src/com/sun/prism/MultiTexture.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/MultiTexture.java	Tue Apr 09 09:33:44 2013 -0700
@@ -243,6 +243,73 @@
     }
 
     @Override
+    public void lock() {
+        for (Texture tex : textures) {
+            tex.lock();
+        }
+    }
+
+    @Override
+    public void unlock() {
+        for (Texture tex : textures) {
+            tex.unlock();
+        }
+    }
+
+    @Override
+    public boolean isLocked() {
+        for (Texture tex : textures) {
+            if (tex.isLocked()) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public int getLockCount() {
+        int count = 0;
+        for (Texture tex : textures) {
+            count = Math.max(count, tex.getLockCount());
+        }
+        return count;
+    }
+
+    @Override
+    public void assertLocked() {
+        for (Texture tex : textures) {
+            tex.assertLocked();
+        }
+    }
+
+    @Override
+    public void makePermanent() {
+        for (Texture tex : textures) {
+            tex.makePermanent();
+        }
+    }
+
+    @Override
+    public void contentsUseful() {
+        for (Texture tex : textures) {
+            tex.contentsUseful();
+        }
+    }
+
+    @Override
+    public void contentsNotUseful() {
+        for (Texture tex : textures) {
+            tex.contentsNotUseful();
+        }
+    }
+
+    @Override
+    public boolean isSurfaceLost() {
+        for (Texture tex : textures) {
+            if (tex.isSurfaceLost()) return true;
+        }
+        return false;
+    }
+
+    @Override
     public void dispose() {
         for (Texture tex : textures) {
             tex.dispose();
--- a/prism-common/src/com/sun/prism/Presentable.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/Presentable.java	Tue Apr 09 09:33:44 2013 -0700
@@ -29,6 +29,17 @@
 
 public interface Presentable extends RenderTarget {
     /**
+     * Locks any underlying resources needed for a createGraphics/prepare/present
+     * sequence and returns a boolean indicating if the presentable needs to be
+     * recreated.
+     * The resources will be unlocked in either {@link #prepare()} or
+     * {@link #present()}.
+     * 
+     * @return true if the caller should recreate the Presentable
+     */
+    public boolean lockResources();
+
+    /**
      * display the indicated region to the user.
      * @param dirtyregion display region or null for full area
      * @return true if the provided region was successfully displayed,
--- a/prism-common/src/com/sun/prism/RTTexture.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/RTTexture.java	Tue Apr 09 09:33:44 2013 -0700
@@ -32,13 +32,4 @@
     public boolean readPixels(Buffer pixels);
     public boolean readPixels(Buffer pixels, int x, int y, int width, int height);
     public boolean isVolatile();
-
-    /**
-     * Called by code wanting to know if the RTTexture's surface is lost. This happens
-     * in some cases (mostly on Windows) when, for example, the user presses Ctrl+Alt+Delete,
-     * or the system goes to sleep.
-     * @return True if the backing surface of this RTTexture is gone and the image is therefore
-     *         no longer usable. False if it is still OK.
-     */
-    public boolean isSurfaceLost();
 }
--- a/prism-common/src/com/sun/prism/ResourceFactory.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/ResourceFactory.java	Tue Apr 09 09:33:44 2013 -0700
@@ -25,6 +25,7 @@
 
 package com.sun.prism;
 
+import com.sun.prism.impl.TextureResourcePool;
 import com.sun.prism.impl.VertexBuffer;
 import com.sun.prism.shape.ShapeRep;
 
@@ -42,6 +43,8 @@
 
     public boolean isDeviceReady();
 
+    public TextureResourcePool getTextureResourcePool();
+
     /**
      * Returns a new {@code Texture} containing the pixels from the given
      * image with the indicated texture edge wrap mode.
--- a/prism-common/src/com/sun/prism/Texture.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/Texture.java	Tue Apr 09 09:33:44 2013 -0700
@@ -408,4 +408,22 @@
      * nearest neighbor filtering
      */
     public void setLinearFiltering(boolean linear);
+
+    public void lock();
+    public void unlock();
+    public boolean isLocked();
+    public int getLockCount();
+    public void assertLocked();
+    public void makePermanent();
+    public void contentsUseful();
+    public void contentsNotUseful();
+
+    /**
+     * Called by code wanting to know if the RTTexture's surface is lost. This happens
+     * in some cases (mostly on Windows) when, for example, the user presses Ctrl+Alt+Delete,
+     * or the system goes to sleep.
+     * @return True if the backing surface of this RTTexture is gone and the image is therefore
+     *         no longer usable. False if it is still OK.
+     */
+    public boolean isSurfaceLost();
 }
--- a/prism-common/src/com/sun/prism/image/CompoundCoords.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/image/CompoundCoords.java	Tue Apr 09 09:33:44 2013 -0700
@@ -27,6 +27,7 @@
 
 import com.sun.prism.Graphics;
 import com.sun.prism.ResourceFactory;
+import com.sun.prism.Texture;
 
 public class CompoundCoords {
     // position in the sub-Image matrix
@@ -89,7 +90,9 @@
         int idx = 0;
         for (int y = yImg0; y <= yImg1; ++y) {
             for (int x = xImg0; x <= xImg1; ++x) {
-                tileCoords[idx++].draw(t.getTile(x, y, factory), g, xS, yS);
+                Texture tex = t.getTile(x, y, factory);
+                tileCoords[idx++].draw(tex, g, xS, yS);
+                tex.unlock();
             }
         }
     }
--- a/prism-common/src/com/sun/prism/image/CompoundTexture.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/image/CompoundTexture.java	Tue Apr 09 09:33:44 2013 -0700
@@ -40,6 +40,12 @@
     public Texture getTile(int x, int y, ResourceFactory factory) {
         int idx = x + y*uSections;
         Texture tex = texTiles[idx];
+        if (tex != null) {
+            tex.lock();
+            if (tex.isSurfaceLost()) {
+                texTiles[idx] = tex = null;
+            }
+        }
         if (tex == null) {
             tex = factory.createTexture(tiles[idx],
                                         Texture.Usage.STATIC,
--- a/prism-common/src/com/sun/prism/impl/BaseContext.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/impl/BaseContext.java	Tue Apr 09 09:33:44 2013 -0700
@@ -179,6 +179,12 @@
     public Texture getMaskTexture(MaskData maskData, boolean canScale) {
         int maskW = maskData.getWidth();
         int maskH = maskData.getHeight();
+        if (maskTex != null) {
+            maskTex.lock();
+            if (maskTex.isSurfaceLost()) {
+                maskTex = null;
+            }
+        }
         if (maskTex == null ||
             maskTex.getContentWidth()  < maskW ||
             maskTex.getContentHeight() < maskH)
@@ -217,6 +223,12 @@
         if (rectTex == null) {
             createRectTexture();
         }
+
+        // rectTex is left permanent and locked so it never
+        // goes away or needs to be checked for isSurfaceLost(), but we
+        // add a lock here so that the caller can unlock without knowing
+        // our inner implementation details
+        rectTex.lock();
         return rectTex;
     }
 
@@ -251,6 +263,11 @@
         Texture tex =
             getResourceFactory().createMaskTexture(texDim, texDim,
                                                    WrapMode.CLAMP_NOT_NEEDED);
+        // rectTex remains permanently locked, useful, and permanent
+        // an additional lock is added when a caller calls getWrapGreientTeture for
+        // them to unlock
+        tex.contentsUseful();
+        tex.makePermanent();
         PixelFormat pf = tex.getPixelFormat();
         int scan = texDim * pf.getBytesPerPixelUnit();
         tex.update(ByteBuffer.wrap(mask), pf,
@@ -263,6 +280,11 @@
         if (wrapRectTex == null) {
             Texture tex =
                 getResourceFactory().createMaskTexture(2, 2, WrapMode.CLAMP_TO_EDGE);
+            // wrapRectTex remains permanently locked, useful, and permanent
+            // an additional lock is added when a caller calls getWrapGreientTeture for
+            // them to unlock
+            tex.contentsUseful();
+            tex.makePermanent();
             int w = tex.getPhysicalWidth();
             int h = tex.getPhysicalHeight();
             if (PrismSettings.verbose) {
@@ -284,6 +306,12 @@
                        scan, false);
             wrapRectTex = tex;
         }
+
+        // wrapRectTex is left permanent and locked so it never
+        // goes away or needs to be checked for isSurfaceLost(), but we
+        // add a lock here so that the caller can unlock without knowing
+        // our inner implementation details
+        wrapRectTex.lock();
         return wrapRectTex;
     }
 
@@ -358,6 +386,8 @@
             Texture tex =
                 getResourceFactory().createMaskTexture(texDim, texDim,
                                                        WrapMode.CLAMP_NOT_NEEDED);
+            tex.contentsUseful();
+            tex.makePermanent();
             PixelFormat pf = tex.getPixelFormat();
             int scan = texDim * pf.getBytesPerPixelUnit();
             tex.update(ByteBuffer.wrap(mask), pf,
@@ -365,6 +395,12 @@
                        scan, false);
             ovalTex = tex;
         }
+
+        // ovalTex is left permanent and locked so it never
+        // goes away or needs to be checked for isSurfaceLost(), but we
+        // add a lock here so that the caller can unlock without knowing
+        // our inner implementation details
+        ovalTex.lock();
         return ovalTex;
     }
 
@@ -380,6 +416,13 @@
             paintBuffer = ByteBuffer.wrap(new byte[sizeInBytes]);
         }
 
+        if (paintTex != null) {
+            paintTex.lock();
+            if (paintTex.isSurfaceLost()) {
+                paintTex = null;
+            }
+        }
+
         if (paintTex == null ||
             paintTex.getContentWidth()  < paintW ||
             paintTex.getContentHeight() < paintH)
--- a/prism-common/src/com/sun/prism/impl/BaseResourceFactory.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/impl/BaseResourceFactory.java	Tue Apr 09 09:33:44 2013 -0700
@@ -129,27 +129,45 @@
             throw new IllegalArgumentException("no caching for "+wrapMode);
         }
          Texture tex = texCache.get(image);
+         if (tex != null) {
+             tex.lock();
+             if (tex.isSurfaceLost()) {
+                 texCache.remove(image);
+                 tex = null;
+             }
+         }
          int serial = image.getSerial();
          if (tex == null) {
             // Try to share a converted texture from the other cache
-            tex = (wrapMode == WrapMode.REPEAT
+            Texture othertex = (wrapMode == WrapMode.REPEAT
                    ? clampTexCache
                    : repeatTexCache).get(image);
-            if (tex != null) {
-                // This conversion operation will fail if the texture is
-                // _SIMULATED
-                tex = tex.getSharedTexture(wrapMode);
-                if (tex != null) {
-                    texCache.put(image, tex);
+            if (othertex != null) {
+                othertex.lock();
+                if (!othertex.isSurfaceLost()) {
+                    // This conversion operation will fail if the texture is
+                    // _SIMULATED
+                    tex = othertex.getSharedTexture(wrapMode);
+                    if (tex != null) {
+                        // Technically, our shared texture will maintain that
+                        // the contents are useful, but for completeness we
+                        // will register both references as "useful"
+                        tex.contentsUseful();
+                        texCache.put(image, othertex);
+                    }
                 }
+                othertex.unlock();
             }
         }
         if (tex == null) {
+            int w = image.getWidth();
+            int h = image.getHeight();
+            TextureResourcePool pool = getTextureResourcePool();
+            long size = pool.estimateTextureSize(w, h, image.getPixelFormat());
+            if (!pool.prepareForAllocation(size)) {
+                return null;
+            }
             tex = createTexture(image, Usage.DEFAULT, wrapMode);
-            if (tex == null) {
-                clearTextureCache();
-                tex = createTexture(image, Usage.DEFAULT, wrapMode);
-            }
             if (tex != null) {
                 tex.setLastImageSerial(serial);
                 texCache.put(image, tex);
@@ -175,6 +193,7 @@
         // so pass skipFlush=true here...
         if (tex != null) {
             tex.update(image, 0, 0, w, h, true);
+            tex.contentsUseful();
         }
         return tex;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prism-common/src/com/sun/prism/impl/BaseResourcePool.java	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.prism.impl;
+
+/**
+ * The base implementation of the {@link ResourcePool} interface, providing
+ * bookkeeping for the {@link managed()} method and support for sharing
+ * resources amongst multiple pools.
+ */
+public abstract class BaseResourcePool<T> implements ResourcePool<T> {
+    long managedSize;
+    final long maxSize;
+    final ResourcePool sharedParent;
+
+    protected BaseResourcePool() {
+        this(null, Long.MAX_VALUE);
+    }
+
+    protected BaseResourcePool(long max) {
+        this(null, max);
+    }
+
+    protected BaseResourcePool(ResourcePool parent) {
+        this(parent, parent.max());
+    }
+
+    protected BaseResourcePool(ResourcePool parent, long max) {
+        this.sharedParent = parent;
+        this.maxSize = ((parent == null)
+                        ? max
+                        : Math.min(parent.max(), max));
+    }
+
+    @Override
+    public final long managed() {
+        return managedSize;
+    }
+
+    @Override
+    public long used() {
+        if (sharedParent != null) {
+            return sharedParent.used();
+        }
+        return managedSize;
+    }
+
+    @Override
+    public final long max() {
+        return maxSize;
+    }
+
+    @Override
+    public boolean prepareForAllocation(long size) {
+        if (used() + size <= target()) return true;
+        ManagedResource.cleanup(this, ManagedResource.PruningLevel.OBSOLETE);
+        if (used() + size <= target()) return true;
+        ManagedResource.cleanup(this, ManagedResource.PruningLevel.UNINTERESTING);
+        if (used() + size <= target()) return true;
+        ManagedResource.cleanup(this, ManagedResource.PruningLevel.ALL_UNLOCKED);
+        return (used() + size <= max());
+    }
+
+    @Override
+    public final void recordAllocated(long size) {
+        managedSize += size;
+    }
+
+    @Override
+    public final void resourceManaged(T resource) {
+        recordAllocated(size(resource));
+    }
+
+    @Override
+    public final void resourceFreed(T resource) {
+        recordFree(size(resource));
+    }
+
+    @Override
+    public final void recordFree(long size) {
+        managedSize -= size;
+        if (managedSize < 0) {
+            throw new IllegalStateException("Negative resource amount");
+        }
+    }
+}
--- a/prism-common/src/com/sun/prism/impl/BaseTexture.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/impl/BaseTexture.java	Tue Apr 09 09:33:44 2013 -0700
@@ -30,7 +30,9 @@
 import com.sun.prism.Texture;
 import java.nio.Buffer;
 
-public abstract class BaseTexture extends BaseGraphicsResource implements Texture {
+public abstract class BaseTexture<T extends ManagedResource> implements Texture {
+
+    protected final T resource;
 
     private final PixelFormat format;
     private final int physicalWidth;
@@ -45,8 +47,8 @@
     private boolean linearFiltering = true;
     private int lastImageSerial;
 
-    protected BaseTexture(BaseTexture sharedTex, WrapMode newMode) {
-        super(sharedTex);
+    protected BaseTexture(BaseTexture<T> sharedTex, WrapMode newMode) {
+        this.resource = sharedTex.resource;
         this.format = sharedTex.format;
         this.wrapMode = newMode;
         this.physicalWidth = sharedTex.physicalWidth;
@@ -57,31 +59,20 @@
         this.contentHeight = sharedTex.contentHeight;
     }
 
-    protected BaseTexture(PixelFormat format, WrapMode wrapMode,
+    protected BaseTexture(T resource,
+                          PixelFormat format, WrapMode wrapMode,
+                          int width, int height)
+    {
+        this(resource, format, wrapMode, width, height, 0, 0, width, height);
+    }
+
+    protected BaseTexture(T resource,
+                          PixelFormat format, WrapMode wrapMode,
                           int physicalWidth, int physicalHeight,
                           int contentX, int contentY,
-                          int contentWidth, int contentHeight,
-                          Disposer.Record disposerRecord)
+                          int contentWidth, int contentHeight)
     {
-        super(disposerRecord);
-        this.format = format;
-        this.wrapMode = wrapMode;
-        this.physicalWidth = physicalWidth;
-        this.physicalHeight = physicalHeight;
-        this.contentX = contentX;
-        this.contentY = contentY;
-        this.contentWidth = contentWidth;
-        this.contentHeight = contentHeight;
-    }
-
-    protected BaseTexture(PixelFormat format, WrapMode wrapMode,
-                          int physicalWidth, int physicalHeight,
-                          int contentX, int contentY,
-                          int contentWidth, int contentHeight,
-                          float u0, float v0, float u1, float v1,
-                          Disposer.Record disposerRecord)
-    {
-        super(disposerRecord);
+        this.resource = resource;
         this.format = format;
         this.wrapMode = wrapMode;
         this.physicalWidth = physicalWidth;
@@ -176,6 +167,56 @@
     }
 
     @Override
+    public final void lock() {
+        resource.lock();
+    }
+
+    @Override
+    public final boolean isLocked() {
+        return resource.isLocked();
+    }
+
+    @Override
+    public final int getLockCount() {
+        return resource.getLockCount();
+    }
+
+    @Override
+    public final void assertLocked() {
+        resource.assertLocked();
+    }
+
+    @Override
+    public final void unlock() {
+        resource.unlock();
+    }
+
+    @Override
+    public final void makePermanent() {
+        resource.makePermanent();
+    }
+
+    @Override
+    public final void contentsUseful() {
+        resource.contentsUseful();
+    }
+
+    @Override
+    public final void contentsNotUseful() {
+        resource.contentsNotUseful();
+    }
+
+    @Override
+    public final boolean isSurfaceLost() {
+        return !resource.isValid();
+    }
+
+    @Override
+    public final void dispose() {
+        resource.dispose();
+    }
+
+    @Override
     public void update(Image img) {
         update(img, 0, 0);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prism-common/src/com/sun/prism/impl/DisposerManagedResource.java	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.prism.impl;
+
+public abstract class DisposerManagedResource<T> extends ManagedResource<T> {
+    Object referent;
+
+    public DisposerManagedResource(T resource, ResourcePool pool,
+                                   Disposer.Record record)
+    {
+        super(resource, pool);
+        this.referent = new Object();
+        Disposer.addRecord(referent, record);
+    }
+}
--- a/prism-common/src/com/sun/prism/impl/GlyphCache.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/impl/GlyphCache.java	Tue Apr 09 09:33:44 2013 -0700
@@ -101,6 +101,8 @@
             ResourceFactory factory = context.getResourceFactory();
             Texture tex = factory.createMaskTexture(WIDTH, HEIGHT,
                                                     WrapMode.CLAMP_NOT_NEEDED);
+            tex.contentsUseful();
+            tex.makePermanent();
             tex.setLinearFiltering(false);
             packer = new RectanglePacker(tex, WIDTH, HEIGHT);
             packerMap.put(context, packer);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prism-common/src/com/sun/prism/impl/ManagedResource.java	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.prism.impl;
+
+import com.sun.prism.GraphicsResource;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public abstract class ManagedResource<T> implements GraphicsResource {
+    private static final boolean trackLockSources = false;
+    private static WeakLinkedList resourceHead = new WeakLinkedList();
+
+    public static enum PruningLevel {
+        OBSOLETE, UNINTERESTING, ALL_UNLOCKED
+    }
+
+    public static void cleanup(ResourcePool pool, PruningLevel plevel) {
+        if (PrismSettings.poolDebug) {
+            switch (plevel) {
+                case OBSOLETE: System.err.print("Pruning"); break;
+                case UNINTERESTING: System.err.print("Cleaning up"); break;
+                case ALL_UNLOCKED: System.err.print("Aggressively cleaning up"); break;
+                default: throw new InternalError("Unrecognized pruning level: "+plevel);
+            }
+            System.err.println(" pool: "+pool);
+            printSummary(false);
+        }
+        long wasused = pool.used();
+        WeakLinkedList prev = resourceHead;
+        WeakLinkedList cur = prev.next;
+        while (cur != null) {
+            ManagedResource mr = cur.getResource();
+            if (mr == null || !mr.isValid()) {
+                if (PrismSettings.poolDebug) {
+                    System.err.println("pruning: "+mr+" ("+cur.size+") "+
+                                       ((mr == null) ? "" :
+                                        ((mr.isPermanent() ? " perm " : "") +
+                                         (mr.isLocked() ? " lock " : "") +
+                                         (mr.isInteresting() ? " int " : ""))));
+                }
+                cur.pool.recordFree(cur.size);
+                cur = cur.next;
+                prev.next = cur;
+            } else if (plevel != PruningLevel.OBSOLETE &&
+                       mr.getPool() == pool &&
+                       !mr.isPermanent() &&
+                       !mr.isLocked() &&
+                       (plevel == PruningLevel.ALL_UNLOCKED || !mr.isInteresting()))
+            {
+                if (PrismSettings.poolDebug) {
+                    System.err.println("disposing: "+mr+" ("+cur.size+") "+
+                                       (mr.isPermanent() ? " perm " : "") +
+                                       (mr.isLocked() ? " lock " : "") +
+                                       (mr.isInteresting() ? " int " : ""));
+                }
+                mr.free();
+                mr.resource = null;
+                cur.pool.recordFree(cur.size);
+                cur = cur.next;
+                prev.next = cur;
+            } else {
+                prev = cur;
+                cur = cur.next;
+            }
+        }
+        if (PrismSettings.poolDebug) {
+            long isused = pool.used();
+            System.err.println("cleaned up "+(wasused - isused)+" from pool: "+pool);
+            printSummary(false);
+        }
+    }
+
+    public static boolean anyLockedResources() {
+        for (WeakLinkedList cur = resourceHead.next; cur != null; cur = cur.next) {
+            ManagedResource mr = cur.getResource();
+            if (mr != null && mr.isValid() && !mr.isPermanent() && mr.isLocked()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static void printSummary() {
+        printSummary(true);
+    }
+
+    public static void printSummary(boolean printlocksources) {
+        int numgone = 0;
+        int numlocked = 0;
+        int numpermanent = 0;
+        int numinteresting = 0;
+        int total = 0;
+        HashMap<ResourcePool, ResourcePool> poolsSeen = new HashMap<ResourcePool, ResourcePool>();
+        for (WeakLinkedList cur = resourceHead.next; cur != null; cur = cur.next) {
+            ManagedResource mr = cur.getResource();
+            total++;
+            if (mr == null || !mr.isValid()) {
+                numgone++;
+            } else {
+                ResourcePool pool = mr.getPool();
+                if (!poolsSeen.containsKey(pool)) {
+                    poolsSeen.put(pool, pool);
+                    double percentUsed = pool.used() * 100.0 / pool.max();
+                    double percentManaged = pool.managed() * 100.0 / pool.max();
+                    String str =
+                        String.format("%s: %,d used (%.1f%%), %,d managed (%.1f%%), %,d total",
+                                      pool, pool.used(), percentUsed,
+                                      pool.managed(), percentManaged,
+                                      pool.max());
+                    System.err.println(str);
+                }
+                if (mr.isPermanent()) {
+                    numpermanent++;
+                } else if (mr.isLocked()) {
+                    numlocked++;
+                    if (trackLockSources && printlocksources) {
+                        ArrayList<Throwable> list = mr.lockedFrom;
+                        for (Throwable th : list) {
+                            th.printStackTrace(System.err);
+                        }
+                        mr.lockedFrom.clear();
+                    }
+                }
+                if (mr.isInteresting()) {
+                    numinteresting++;
+                }
+            }
+        }
+        System.err.println(total+" total resources being managed");
+        System.err.println(numpermanent+" permanent resources ("+
+                           Math.round(numpermanent * 1000.0 / total)/10.0+"%)");
+        System.err.println(numlocked+" resources locked ("+
+                           Math.round(numlocked * 1000.0 / total)/10.0+"%)");
+        System.err.println(numinteresting+" resources contain interesting data ("+
+                           Math.round(numinteresting * 1000.0 / total)/10.0+"%)");
+        System.err.println(numgone+" resources disappeared ("+
+                           Math.round(numgone * 1000.0 / total)/10.0+"%)");
+        System.err.println();
+    }
+
+    protected T resource;
+    private final ResourcePool<T> pool;
+    private int lockcount;
+    private int employcount;
+    ArrayList<Throwable> lockedFrom;
+    private boolean permanent;
+
+    protected ManagedResource(T resource, ResourcePool<T> pool) {
+        this.resource = resource;
+        this.pool = pool;
+        if (trackLockSources) {
+            this.lockedFrom = new ArrayList<Throwable>();
+        }
+        link();
+        lock();
+    }
+
+    private void link() {
+        resourceHead.insert(this);
+    }
+
+    private void unlink() {
+        WeakLinkedList prev = resourceHead;
+        WeakLinkedList cur = prev.next;
+        while (cur != null) {
+            ManagedResource mr = cur.getResource();
+            if (mr == null || mr == this) {
+                cur.pool.recordFree(cur.size);
+                cur = cur.next;
+                prev.next = cur;
+                if (mr == this) {
+                    break;
+                }
+            } else {
+                prev = cur;
+                cur = cur.next;
+            }
+        }
+    }
+
+    public final T getResource() {
+        assertLocked();
+        return resource;
+    }
+
+    public final ResourcePool getPool() {
+        return pool;
+    }
+
+    public final boolean isValid() {
+        return resource != null;
+    }
+
+    public final boolean isLocked() {
+        return lockcount > 0;
+    }
+
+    public final int getLockCount() {
+        return lockcount;
+    }
+
+    public final void assertLocked() {
+        if (lockcount <= 0) {
+            throw new IllegalStateException("Operation requires resource lock");
+        }
+    }
+
+    public final boolean isPermanent() {
+        return permanent;
+    }
+
+    public final boolean isInteresting() {
+        return employcount > 0;
+    }
+
+    public final int getInterestCount() {
+        return employcount;
+    }
+
+    public void free() {
+    }
+
+    @Override
+    public final void dispose() {
+        if (resource != null) {
+            free();
+            resource = null;
+            unlink();
+        }
+    }
+
+    public final void makePermanent() {
+        assertLocked();
+        permanent = true;
+    }
+
+    public final T lock() {
+        lockcount++;
+        if (trackLockSources && !permanent) {
+            lockedFrom.add(new Throwable(Integer.toString(lockcount)));
+        }
+        return resource;
+    }
+
+    public final void unlock() {
+        assertLocked();
+        lockcount--;
+        if (trackLockSources && !permanent && lockcount == 0) {
+            lockedFrom.clear();
+        }
+    }
+
+    public final void contentsUseful() {
+        assertLocked();
+        employcount++;
+    }
+
+    public final void contentsNotUseful() {
+        if (employcount <= 0) {
+            throw new IllegalStateException("Resource obsoleted too many times");
+        }
+        employcount--;
+    }
+
+    static class WeakLinkedList {
+        final WeakReference<ManagedResource> theResourceRef;
+        final ResourcePool pool;
+        final long size;
+        WeakLinkedList next;
+        
+        WeakLinkedList() {
+            this.theResourceRef = null;
+            this.pool = null;
+            this.size = 0L;
+        }
+
+        WeakLinkedList(ManagedResource mresource, WeakLinkedList next) {
+            this.theResourceRef = new WeakReference<ManagedResource>(mresource);
+            this.pool = mresource.pool;
+            this.size = pool.size(mresource.resource);
+            pool.recordAllocated(size);
+            this.next = next;
+        }
+
+        void insert(ManagedResource resource) {
+            this.next = new WeakLinkedList(resource, next);
+        }
+
+        ManagedResource getResource() {
+            return theResourceRef.get();
+        }
+    }
+}
--- a/prism-common/src/com/sun/prism/impl/PrismSettings.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-common/src/com/sun/prism/impl/PrismSettings.java	Tue Apr 09 09:33:44 2013 -0700
@@ -77,6 +77,10 @@
     public static final boolean noClampToZero;
     public static final boolean disableD3D9Ex;
     public static final boolean allowHiDPIScaling;
+    public static final long maxVram;
+    public static final long targetVram;
+    public static final boolean poolStats;
+    public static final boolean poolDebug;
 
     private PrismSettings() {
     }
@@ -194,6 +198,8 @@
                 tryOrderArr = new String[] { "es2", "sw" };
             } else if (PlatformUtil.isIOS()) {
                 tryOrderArr = new String[] { "es2" };
+            } else if (PlatformUtil.isAndroid()) {
+                    tryOrderArr = new String[] { "es2" };
             } else if (PlatformUtil.isLinux()) {
                 tryOrderArr = new String[] { "es2", "sw" };
             } else {
@@ -254,6 +260,11 @@
         
         allowHiDPIScaling = getBoolean(systemProperties, "prism.allowhidpi", true);
 
+        maxVram = getLong(systemProperties, "prism.maxvram", 256 * 1024 * 1024, null);
+        targetVram = getLong(systemProperties, "prism.targetvram", maxVram / 2, null);
+        poolStats = getBoolean(systemProperties, "prism.poolstats", false);
+        poolDebug = getBoolean(systemProperties, "prism.pooldebug", false);
+
         if (verbose) {
             System.out.print("Prism pipeline init order: ");
             for (String s : tryOrder) {
@@ -332,6 +343,31 @@
         return dflt;
     }
 
+    private static long parseLong(String s, long dflt, String errMsg) {
+        if (s != null && s.length() > 0) {
+            long mult = 1;
+            if (s.endsWith("k") || s.endsWith("K")) {
+                mult = 1024L;
+            } else if (s.endsWith("m") || s.endsWith("M")) {
+                mult = 1024L * 1024L;
+            } else if (s.endsWith("g") || s.endsWith("G")) {
+                mult = 1024L * 1024L * 1024L;
+            }
+            if (mult > 1) {
+                s = s.substring(0, s.length() - 1);
+            }
+            try {
+                return Long.parseLong(s) * mult;
+            } catch (Exception e) {
+                if (errMsg != null) {
+                    System.err.println(errMsg);
+                }
+            }
+        }
+
+        return dflt;
+    }
+
     /* A simple version of String.split(), since that isn't available on CDC */
     private static String[] split(String str, String delim) {
         StringTokenizer st = new StringTokenizer(str, delim);
@@ -369,4 +405,14 @@
                         dflt,
                         errMsg);
     }
+
+    private static long getLong(Properties properties,
+                                String key,
+                                long dflt,
+                                String errMsg)
+    {
+        return parseLong(properties.getProperty(key),
+                         dflt,
+                         errMsg);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prism-common/src/com/sun/prism/impl/ResourcePool.java	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.prism.impl;
+
+/**
+ * An interface for tracking the usage of a particular resource from which
+ * managed resources are allocated.
+ * A given resource pool may share its underlying space with another
+ * resource pool, such as the case of allocating textures from the Java
+ * heap.
+ * In the case of a shared resource, the {@link used()} and {@link max()}
+ * methods will return absolute values indicating the amounts used or
+ * available for all resources that come from the shared pool, but the
+ * {@link managed()} method will only indicate the amount of the resource
+ * used for managed resources and the {@link target()} method will return
+ * the amount of the total shared resource that the allocation methods
+ * should attempt to stay under.
+ * <pre>
+ *     long newsize = ...; // size of new resource allocation
+ *     if (pool.used() + newsize >= pool.target()) {
+ *         cleanup(pool);
+ *         // possibly multiple passes of increasing aggressiveness
+ *     }
+ *     if (pool.used() + newsize >= pool.max()) {
+ *         throw OOM();
+ *     }
+ *     allocate(newsize);
+ * </pre>
+ * The amounts and sizes returned from the methods should all be in the
+ * same units, usually bytes.
+ * 
+ * @see ManagedResource
+ */
+public interface ResourcePool<T> {
+    /**
+     * The amount of a resource currently being used to hold any kind of
+     * resource, whether managed or not.
+     */
+    public long used();
+
+    /**
+     * The amount of this resource currently being used to hold managed
+     * resources.
+     * This amount may be less than the amount returned by the {@link used()}
+     * method if the pool is shared amongst other resources.
+     */
+    public long managed();
+
+    /**
+     * The total space available in this pool for allocating any kind of
+     * resource, even unmanaged resources, and including those resources
+     * already allocated.
+     */
+    public long max();
+
+    /**
+     * The target of the maximum amount of space in this resource pool that
+     * should be used so as to be friendly to other parts of the system.
+     * This number must be less than or equal to the amount returned by the
+     * {@link max()} method.
+     */
+    public long target();
+
+    /**
+     * The estimated size of the indicated resource.
+     * 
+     * @param resource the resource to be measured
+     * @return the space within this resource pool that the object occupies.
+     */
+    public long size(T resource);
+
+    /**
+     * Record the indicated amount of the resource as being allocated for
+     * a {@link ManagedResource}.
+     * 
+     * @param size the amount of the resource to be indicated as managed.
+     */
+    public void recordAllocated(long size);
+
+    /**
+     * Record the indicated amount of the resource as no longer being
+     * held in a {@link ManagedResource}.
+     * 
+     * @param size the amount of the resource to remove from the managed amount.
+     */
+    public void recordFree(long size);
+
+    /**
+     * Record the indicated amount of the resource as being allocated for
+     * a {@link ManagedResource}.
+     * 
+     * @param resource the resource that is now being managed
+     */
+    public void resourceManaged(T resource);
+
+    /**
+     * Record the indicated amount of the resource as no longer being
+     * held in a {@link ManagedResource}.
+     * 
+     * @param resource the resource that is freed, no longer being managed
+     */
+    public void resourceFreed(T resource);
+
+    /**
+     * Prepare for an allocation of a resource from this pool of the
+     * indicated size by freeing up uninteresting resources until the
+     * allocation fits within the target() or max() sizes.
+     * 
+     * @param size the size of the resource that is about to be allocated
+     * @return true if there is room for the indicated resource
+     */
+    public boolean prepareForAllocation(long size);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prism-common/src/com/sun/prism/impl/TextureResourcePool.java	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.prism.impl;
+
+import com.sun.prism.PixelFormat;
+
+/**
+ * A {@link ResourcePool} that manages memory for textures.
+ * This interface only adds a couple of methods for computing
+ * the size of a potential new texture allocation.
+ */
+public interface TextureResourcePool<T> extends ResourcePool<T> {
+    public long estimateTextureSize(int width, int height, PixelFormat format);
+    public long estimateRTTextureSize(int width, int height, boolean hasDepth);
+}
--- a/prism-j2d/src/com/sun/prism/j2d/J2DPresentable.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-j2d/src/com/sun/prism/j2d/J2DPresentable.java	Tue Apr 09 09:33:44 2013 -0700
@@ -194,13 +194,17 @@
     IntBuffer ib;
     J2DRTTexture readbackBuffer;
 
-    protected J2DPresentable(java.awt.image.BufferedImage buffer,
-                             J2DResourceFactory factory)
+    J2DPresentable(java.awt.image.BufferedImage buffer,
+                   J2DResourceFactory factory)
     {
         this.buffer = buffer;
         this.factory = factory;
     }
 
+    public boolean lockResources() {
+        return false;
+    }
+
     public void setNeedsResize() {
         this.needsResize = true;
     }
--- a/prism-j2d/src/com/sun/prism/j2d/J2DPrismGraphics.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-j2d/src/com/sun/prism/j2d/J2DPrismGraphics.java	Tue Apr 09 09:33:44 2013 -0700
@@ -300,6 +300,7 @@
             Texture tex =
                 getResourceFactory().getCachedTexture(imgpat.getImage(), WrapMode.REPEAT);
             java.awt.image.BufferedImage bimg = ((J2DTexture) tex).getBufferedImage();
+            tex.unlock();
             return new java.awt.TexturePaint(bimg, tmpRect(x, y, w, h));
         }
         throw new UnsupportedOperationException("Paint "+p+" not supported yet.");
@@ -1036,7 +1037,7 @@
     }
 
     public void releaseReadBackBuffer(RTTexture view) {
-        // NOP
+        target.getReadbackBuffer().unlock();
     }
 
     public PrismCameraImpl getCameraNoClone() {
--- a/prism-j2d/src/com/sun/prism/j2d/J2DRTTexture.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-j2d/src/com/sun/prism/j2d/J2DRTTexture.java	Tue Apr 09 09:33:44 2013 -0700
@@ -31,6 +31,7 @@
 import com.sun.prism.PixelFormat;
 import com.sun.prism.RTTexture;
 
+import java.awt.image.BufferedImage;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
@@ -40,12 +41,14 @@
     private boolean opaque;
 
     J2DRTTexture(int w, int h, J2DResourceFactory factory) {
-        super(PixelFormat.INT_ARGB_PRE, WrapMode.CLAMP_TO_ZERO, w, h);
+        super(new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE),
+              IntArgbPreUpdater.INT_ARGB_PRE_INSTANCE, WrapMode.CLAMP_TO_ZERO);
         this.factory = factory;
         this.opaque = false;
     }
 
     public int[] getPixels() {
+        BufferedImage bimg = getBufferedImage();
         java.awt.image.DataBuffer db = bimg.getRaster().getDataBuffer();
         if (db instanceof java.awt.image.DataBufferInt) {
             return ((java.awt.image.DataBufferInt) db).getData();
@@ -91,23 +94,20 @@
     }
 
     public Graphics createGraphics() {
+        BufferedImage bimg = getBufferedImage();
         J2DPresentable presentable = J2DPresentable.create(bimg, factory);
         java.awt.Graphics2D g2d = bimg.createGraphics();
         return new J2DPrismGraphics(presentable, g2d);
     }
 
     java.awt.Graphics2D createAWTGraphics2D() {
-        return bimg.createGraphics();
+        return getBufferedImage().createGraphics();
     }
 
     public Screen getAssociatedScreen() {
         return factory.getScreen();
     }
 
-    @Override public boolean isSurfaceLost() {
-        return false;
-    }
-
     @Override
     public void update(Image img) {
         throw new UnsupportedOperationException("update() not supported for RTTextures");
--- a/prism-j2d/src/com/sun/prism/j2d/J2DResourceFactory.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-j2d/src/com/sun/prism/j2d/J2DResourceFactory.java	Tue Apr 09 09:33:44 2013 -0700
@@ -37,6 +37,8 @@
 import com.sun.prism.Texture.WrapMode;
 import com.sun.prism.impl.BaseResourceFactory;
 import com.sun.prism.impl.BaseRenderingContext;
+import com.sun.prism.impl.ManagedResource;
+import com.sun.prism.impl.TextureResourcePool;
 import com.sun.prism.impl.VertexBuffer;
 import com.sun.prism.impl.shape.BasicShapeRep;
 import com.sun.prism.shape.ShapeRep;
@@ -49,6 +51,10 @@
         this.screen = screen;
     }
 
+    public TextureResourcePool getTextureResourcePool() {
+        return J2DTexturePool.instance;
+    }
+
     Screen getScreen() {
         return screen;
     }
@@ -76,6 +82,11 @@
     }
 
     public RTTexture createRTTexture(int width, int height, WrapMode wrapMode) {
+        J2DTexturePool pool = J2DTexturePool.instance;
+        long size = pool.estimateRTTextureSize(width, height, false);
+        if (!pool.prepareForAllocation(size)) {
+            return null;
+        }
         return new J2DRTTexture(width, height, this);
     }
 
@@ -83,7 +94,7 @@
                                  Usage usageHint, WrapMode wrapMode,
                                  int w, int h)
     {
-        return new J2DTexture(formatHint, wrapMode, w, h);
+        return J2DTexture.create(formatHint, wrapMode, w, h);
     }
 
     public Texture createTexture(MediaFrame vdb) {
@@ -101,8 +112,8 @@
             }
         }
 
-        tex = new J2DTexture(vdb.getPixelFormat(), WrapMode.CLAMP_TO_EDGE,
-                             vdb.getWidth(), vdb.getHeight());
+        tex = J2DTexture.create(vdb.getPixelFormat(), WrapMode.CLAMP_TO_EDGE,
+                                vdb.getWidth(), vdb.getHeight());
         vdb.releaseFrame();
         return tex;
     }
--- a/prism-j2d/src/com/sun/prism/j2d/J2DTexture.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-j2d/src/com/sun/prism/j2d/J2DTexture.java	Tue Apr 09 09:33:44 2013 -0700
@@ -26,25 +26,35 @@
 package com.sun.prism.j2d;
 
 import com.sun.prism.MediaFrame;
-import com.sun.prism.Image;
 import com.sun.prism.PixelFormat;
 import com.sun.prism.Texture;
 import com.sun.prism.Texture.WrapMode;
+import com.sun.prism.impl.BaseTexture;
+import com.sun.prism.impl.ManagedResource;
+import com.sun.prism.j2d.J2DTexture.J2DTexResource;
 import java.awt.image.BufferedImage;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
 
-class J2DTexture implements Texture {
-    protected BufferedImage bimg;
-    private final WrapMode wrapMode;
+class J2DTexture extends BaseTexture<J2DTexResource> {
 
-    private Updater updater;
-    private boolean linearfiltering = true;
-    private int lastImageSerial;
+    private final Updater updater;
 
-    J2DTexture(PixelFormat format, WrapMode wrapMode, int w, int h) {
+    static class J2DTexResource extends ManagedResource<BufferedImage> {
+        public J2DTexResource(BufferedImage bimg) {
+            super(bimg, J2DTexturePool.instance);
+        }
+
+        @Override
+        public void free() {
+            resource.flush();
+        }
+    }
+
+    static J2DTexture create(PixelFormat format, WrapMode wrapMode, int w, int h) {
         int type;
+        Updater updater;
         switch (format) {
             case BYTE_RGB:
                 type = BufferedImage.TYPE_3BYTE_BGR;
@@ -62,124 +72,33 @@
             default:
                 throw new InternalError("Unrecognized PixelFormat ("+format+")!");
         }
-        this.bimg = new BufferedImage(w, h, type);
-        this.wrapMode = wrapMode;
+        J2DTexturePool pool = J2DTexturePool.instance;
+        long size = J2DTexturePool.size(w, h, type);
+        if (!pool.prepareForAllocation(size)) {
+            return null;
+        }
+        BufferedImage bimg = new BufferedImage(w, h, type);
+        return new J2DTexture(bimg, updater, wrapMode);
+    }
+
+    J2DTexture(BufferedImage bimg, Updater updater, WrapMode wrapMode) {
+        super(new J2DTexResource(bimg), PixelFormat.BYTE_RGB, wrapMode,
+              bimg.getWidth(), bimg.getHeight());
+        this.updater = updater;
     }
 
     J2DTexture(J2DTexture sharedTex, WrapMode altMode) {
-        this.bimg = sharedTex.bimg;
-        this.wrapMode = sharedTex.wrapMode;
+        super(sharedTex, altMode);
         this.updater = sharedTex.updater;
-        this.linearfiltering = sharedTex.linearfiltering;
-        // REMIND: Use indirection to "share" the last serial?
-        this.lastImageSerial = sharedTex.lastImageSerial;
     }
 
-    public void dispose() {
-        bimg.flush();
-        bimg = null;
+    @Override
+    protected Texture createSharedTexture(WrapMode newMode) {
+        return new J2DTexture(this, newMode);
     }
 
     BufferedImage getBufferedImage() {
-        return bimg;
-    }
-
-    public PixelFormat getPixelFormat() {
-        switch (bimg.getType()) {
-            case BufferedImage.TYPE_3BYTE_BGR:
-                return PixelFormat.BYTE_RGB;
-            case BufferedImage.TYPE_BYTE_GRAY:
-                return PixelFormat.BYTE_GRAY;
-            case BufferedImage.TYPE_INT_ARGB_PRE:
-                return PixelFormat.INT_ARGB_PRE;
-            default:
-                throw new InternalError("Unrecognized BufferedImage type ("+bimg.getType()+")!");
-        }
-    }
-
-    public int getPhysicalWidth() {
-        return bimg.getWidth();
-    }
-
-    public int getPhysicalHeight() {
-        return bimg.getHeight();
-    }
-
-    public int getContentX() {
-        return 0;
-    }
-
-    public int getContentY() {
-        return 0;
-    }
-
-    public int getContentWidth() {
-        return bimg.getWidth();
-    }
-
-    public int getContentHeight() {
-        return bimg.getHeight();
-    }
-
-    public WrapMode getWrapMode() {
-        return wrapMode;
-    }
-
-    public Texture getSharedTexture(WrapMode altMode) {
-        if (wrapMode == altMode) {
-            return this;
-        }
-        switch (altMode) {
-            case REPEAT:
-                if (wrapMode != WrapMode.CLAMP_TO_EDGE) {
-                    return null;
-                }
-                break;
-            case CLAMP_TO_EDGE:
-                if (wrapMode != WrapMode.REPEAT) {
-                    return null;
-                }
-            default:
-                return null;
-        }
-        return new J2DTexture(this, altMode);
-    }
-
-    public boolean getLinearFiltering() {
-        return linearfiltering;
-    }
-
-    public void setLinearFiltering(boolean linear) {
-        this.linearfiltering = linear;
-    }
-
-    public int getLastImageSerial() {
-        return lastImageSerial;
-    }
-
-    public void setLastImageSerial(int serial) {
-        lastImageSerial = serial;
-    }
-
-    public void update(Image img) {
-        update(img, 0, 0);
-    }
-
-    public void update(Image img, int dstx, int dsty) {
-        update(img, dstx, dsty, img.getWidth(), img.getHeight());
-    }
-
-    public void update(Image img, int dstx, int dsty, int w, int h) {
-        update(img, dstx, dsty, w, h, false);
-    }
-
-    public void update(Image img, int dstx, int dsty, int srcw, int srch,
-                       boolean skipFlush)
-    {
-        update(img.getPixelBuffer(), img.getPixelFormat(),
-               dstx, dsty, img.getMinX(), img.getMinY(),
-               srcw, srch, img.getScanlineStride(),
-               skipFlush);
+        return resource.getResource();
     }
 
     public void update(Buffer buffer, PixelFormat format,
@@ -188,6 +107,7 @@
                        int srcscan,
                        boolean skipFlush)
     {
+        BufferedImage bimg = getBufferedImage();
         switch (format) {
             case BYTE_RGB:
                 updater.updateFromByteBuffer(bimg, (ByteBuffer) buffer,
@@ -235,6 +155,7 @@
 
         ByteBuffer bbuf = frame.getBuffer();
         bbuf.position(frame.offsetForPlane(0));
+        BufferedImage bimg = getBufferedImage();
         updater.updateFromIntBuffer(bimg, bbuf.asIntBuffer(),
                 0, 0, 0, 0, frame.getWidth(), frame.getHeight(),
                 frame.strideForPlane(0)/4,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prism-j2d/src/com/sun/prism/j2d/J2DTexturePool.java	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.prism.j2d;
+
+import com.sun.prism.PixelFormat;
+import com.sun.prism.impl.BaseResourcePool;
+import com.sun.prism.impl.PrismSettings;
+import com.sun.prism.impl.TextureResourcePool;
+import java.awt.image.BufferedImage;
+
+class J2DTexturePool extends BaseResourcePool<BufferedImage>
+    implements TextureResourcePool<BufferedImage>
+{
+    static final J2DTexturePool instance = new J2DTexturePool();
+
+    private static long maxVram() {
+        long heapmax = Runtime.getRuntime().maxMemory();
+        long setmax = PrismSettings.maxVram;
+        return Math.min(heapmax / 4, setmax);
+    }
+
+    final long targetVram;
+
+    private J2DTexturePool() {
+        super(null, maxVram());
+        targetVram = Math.min(max() / 2, PrismSettings.targetVram);
+    }
+
+    public long target() {
+        return targetVram;
+    }
+
+    @Override
+    public long used() {
+        Runtime r = Runtime.getRuntime();
+        long heapused = r.totalMemory() - r.freeMemory();
+        long heapfree = r.maxMemory() - heapused;
+//        heapfree = max();
+        long managedfree = max() - managed();
+        return max() - Math.min(heapfree, managedfree);
+    }
+
+    static long size(int w, int h, int type) {
+        long size = ((long) w) * ((long) h);
+        switch (type) {
+            case BufferedImage.TYPE_3BYTE_BGR:
+                return size * 3L;
+            case BufferedImage.TYPE_BYTE_GRAY:
+                return size;
+            case BufferedImage.TYPE_INT_ARGB_PRE:
+                return size * 4L;
+            default:
+                throw new InternalError("Unrecognized BufferedImage");
+        }
+    }
+
+    public long size(BufferedImage resource) {
+        return size(resource.getWidth(), resource.getHeight(),
+                    resource.getType());
+    }
+
+    public long estimateTextureSize(int width, int height,
+                                    PixelFormat format)
+    {
+        int type;
+        switch (format) {
+            case BYTE_RGB:
+                type = BufferedImage.TYPE_3BYTE_BGR;
+                break;
+            case BYTE_GRAY:
+                type = BufferedImage.TYPE_BYTE_GRAY;
+                break;
+            case INT_ARGB_PRE:
+            case BYTE_BGRA_PRE:
+                type = BufferedImage.TYPE_INT_ARGB_PRE;
+                break;
+            default:
+                throw new InternalError("Unrecognized PixelFormat ("+format+")!");
+        }
+        return size(width, height, type);
+    }
+
+    public long estimateRTTextureSize(int width, int height,
+                                      boolean hasDepth)
+    {
+        return size(width, height, BufferedImage.TYPE_INT_ARGB_PRE);
+    }
+
+    @Override
+    public String toString() {
+        return "J2D Texture Pool";
+    }
+}
--- a/prism-null/src/com/sun/prism/null3d/DummyRTTexture.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-null/src/com/sun/prism/null3d/DummyRTTexture.java	Tue Apr 09 09:33:44 2013 -0700
@@ -64,10 +64,6 @@
         return getContext().getAssociatedScreen();
     }
 
-    @Override public boolean isSurfaceLost() {
-        return false;
-    }
-
     @Override
     public void update(Image img) {
     }
--- a/prism-null/src/com/sun/prism/null3d/DummyResourceFactory.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-null/src/com/sun/prism/null3d/DummyResourceFactory.java	Tue Apr 09 09:33:44 2013 -0700
@@ -37,6 +37,7 @@
 import com.sun.prism.Texture.WrapMode;
 import com.sun.prism.impl.VertexBuffer;
 import com.sun.prism.impl.BaseRenderingContext;
+import com.sun.prism.impl.TextureResourcePool;
 import com.sun.prism.impl.ps.BaseShaderFactory;
 import com.sun.prism.ps.Shader;
 
@@ -55,6 +56,9 @@
         return context;
     }
 
+    public TextureResourcePool getTextureResourcePool() {
+        return DummyTexturePool.instance;
+    }
 
     @Override
     public DummyTexture createTexture(PixelFormat format,
--- a/prism-null/src/com/sun/prism/null3d/DummySwapChain.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-null/src/com/sun/prism/null3d/DummySwapChain.java	Tue Apr 09 09:33:44 2013 -0700
@@ -50,6 +50,10 @@
         this.h = pState.getHeight();
     }
 
+    public boolean lockResources() {
+        return false;
+    }
+
     public boolean prepare(Rectangle clip) {
         return true;
     }
--- a/prism-null/src/com/sun/prism/null3d/DummyTexture.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-null/src/com/sun/prism/null3d/DummyTexture.java	Tue Apr 09 09:33:44 2013 -0700
@@ -29,10 +29,16 @@
 import com.sun.prism.PixelFormat;
 import com.sun.prism.Texture;
 import com.sun.prism.impl.BaseTexture;
+import com.sun.prism.impl.ManagedResource;
 import com.sun.prism.impl.PrismTrace;
 import java.nio.Buffer;
 
 class DummyTexture extends BaseTexture  {
+    static class DummyManagedResource extends ManagedResource<Object> {
+        DummyManagedResource() {
+            super(new Object(), DummyTexturePool.instance);
+        }
+    };
 
     DummyContext context;
 
@@ -45,10 +51,9 @@
     DummyTexture(DummyContext context, PixelFormat format, WrapMode wrapMode,
                  int contentWidth, int contentHeight, boolean isRTT)
     {
-        super(format, wrapMode,
+        super(new DummyManagedResource(), format, wrapMode,
               contentWidth, contentHeight,
-              0, 0, contentWidth, contentHeight,
-              new DummyResource.DummyRecord());
+              0, 0, contentWidth, contentHeight);
 
         this.context = context;
 
@@ -64,10 +69,6 @@
         return context;
     }
 
-    @Override
-    public void dispose() {
-    }
-
     public void update(Buffer buffer, PixelFormat format, int dstx, int dsty, int srcx, int srcy, int srcw, int srch, int srcscan, boolean skipFlush) {
 
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prism-null/src/com/sun/prism/null3d/DummyTexturePool.java	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.prism.null3d;
+
+import com.sun.prism.PixelFormat;
+import com.sun.prism.impl.BaseResourcePool;
+import com.sun.prism.impl.TextureResourcePool;
+
+public class DummyTexturePool extends BaseResourcePool
+    implements TextureResourcePool
+{
+    public static final DummyTexturePool instance = new DummyTexturePool();
+
+    private DummyTexturePool() {
+        super(256 * 1024 * 1024);
+    }
+
+    public long target() {
+        return max() / 2;
+    }
+
+    public long size(Object resource) {
+        return 0;
+    }
+
+    public long estimateTextureSize(int width, int height, PixelFormat format) {
+        return 0;
+    }
+
+    public long estimateRTTextureSize(int width, int height, boolean hasDepth) {
+        return 0;
+    }
+}
--- a/prism-ps/src/com/sun/prism/impl/ps/BaseShaderContext.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-ps/src/com/sun/prism/impl/ps/BaseShaderContext.java	Tue Apr 09 09:33:44 2013 -0700
@@ -440,6 +440,7 @@
             checkState(g, xform, shader, tex0, tex1);
             updatePaintShader(g, shader, maskType, paint, bx, by, bw, bh);
             updatePerVertexColor(paint, g.getExtraAlpha());
+            if (paintTex != null) paintTex.unlock();
             return shader;
         } else {
             // note that paint is assumed to be a simple Color in this case
@@ -632,6 +633,7 @@
     }
 
     private void setTexture(int texUnit, Texture tex) {
+        if (tex != null) tex.assertLocked();
         if (tex != state.lastTextures[texUnit]) {
             flushVertexBuffer();
             updateTexture(texUnit, tex);
@@ -642,6 +644,11 @@
     //Current RenderTarget is the lcdBuffer after this method.
     public void initLCDBuffer(int width, int height) {
         lcdBuffer = factory.createRTTexture(width, height, Texture.WrapMode.CLAMP_NOT_NEEDED);
+        // TODO: RT-29488 we need to track the uses of the LCD buffer,
+        // but the flow of control through the text methods is
+        // not straight-forward enough for a simple set of lock/unlock
+        // fixes at this time.
+        lcdBuffer.makePermanent();
     }
 
     public void disposeLCDBuffer() {
@@ -670,6 +677,9 @@
     protected void setRenderTarget(RenderTarget target, PrismCameraImpl camera,
                                    boolean depthTest)
     {
+        if (target instanceof Texture) {
+            ((Texture) target).assertLocked();
+        }
         if (state == null ||
             target != state.lastRenderTarget ||
             camera != state.lastCamera ||
--- a/prism-ps/src/com/sun/prism/impl/ps/BaseShaderGraphics.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-ps/src/com/sun/prism/impl/ps/BaseShaderGraphics.java	Tue Apr 09 09:33:44 2013 -0700
@@ -301,6 +301,7 @@
         VertexBuffer vb = context.getVertexBuffer();
         context.validateTextureOp(this, IDENT, tex, null, tex.getPixelFormat());
         vb.addQuad(dx1, dy1, dx2, dy2, tx1, ty1, tx2, ty2);
+        tex.unlock();
     }
 
     @Override
@@ -351,6 +352,7 @@
             VertexBuffer vb = context.getVertexBuffer();
             vb.addQuad(dx1, dy1, dx2, dy2, tx1, ty1, tx2, ty2);
         }
+        maskTex.unlock();
     }
 
     private static float getStrokeExpansionFactor(BasicStroke stroke) {
@@ -1100,6 +1102,7 @@
                                   ou0, ov0, ouc, ov0, ou0, ovc, ouc, ovc,
                                   x1, y1, xc, yc, paintTx);
             }
+            rTex.unlock();
             return true;
         } else {
             System.out.println("Not a 2d transform!");
@@ -1126,6 +1129,7 @@
         vb.addQuad( x1,  y1,  xc,  yc,
                    ou0, ov0, ouc, ovc,
                    paintTx);
+        rTex.unlock();
         return true;
     }
 
@@ -1240,6 +1244,7 @@
                                    u0,  v0,  u1,  v0,  u0,  v1,  u1,  v1,
                                   0, 0);
 //                System.out.print("1"); System.out.flush();
+                rTex.unlock();
                 return true;
             }
             // long thin line (cellw is along the line, cellh is across it)
@@ -1269,6 +1274,7 @@
                                    u0,  v0,  u1,  v0,  u0,  v1,  u1,  v1,
                                   0, 0);
 //                System.out.print("2"); System.out.flush();
+                rTex.unlock();
                 return true;
             }
             // Finally, 3-slice the line (left edge, huge middle, right edge)
@@ -1300,6 +1306,7 @@
                                u1,  v0,  u0,  v0,  u1,  v1,  u0,  v1,
                               0, 0);
 //            System.out.print("3"); System.out.flush();
+            rTex.unlock();
             return true;
         }
         // we could 2 and 3 slice extremely wide short lines, but they
@@ -1335,6 +1342,7 @@
                             u0,  v0,  uc,  v0,  u0,  vc,  uc,  vc,
                             0, 0);
 //        System.out.print("4"); System.out.flush();
+        rTex.unlock();
         return true;
     }
 
@@ -1348,13 +1356,12 @@
             return;
         }
         if (PrismSettings.primTextureSize != 0) {
-            if (fillPrimRect(x, y, w, h,
-                             context.getRectTexture(),
-                             context.getWrapRectTexture(),
-                             x, y, w, h))
-            {
-                return;
-            }
+            Texture rTex = context.getRectTexture();
+            Texture wTex = context.getWrapRectTexture();
+            boolean success = fillPrimRect(x, y, w, h, rTex, wTex, x, y, w, h);
+            rTex.unlock();
+            wTex.unlock();
+            if (success) return;
         }
         renderGeneralRoundedRect(x, y, w, h, 0f, 0f,
                                  MaskType.FILL_PGRAM, null);
@@ -1647,14 +1654,14 @@
                     // Zero length line - NOP for CAP_BUTT
                     return;
                 }
-                if (fillPrimRect(bx - padx,        by - pady,
-                                 bw + padx + padx, bh + pady + pady,
-                                 context.getRectTexture(),
-                                 context.getWrapRectTexture(),
-                                 bx, by, bw, bh))
-                {
-                    return;
-                }
+                Texture rTex = context.getRectTexture();
+                Texture wTex = context.getWrapRectTexture();
+                boolean success = fillPrimRect(bx - padx,        by - pady,
+                                               bw + padx + padx, bh + pady + pady,
+                                               rTex, wTex, bx, by, bw, bh);
+                rTex.unlock();
+                wTex.unlock();
+                if (success) return;
             } else {
                 if (drawPrimDiagonal(x1, y1, x2, y2, lw, cap,
                                      bx, by, bw, bh))
@@ -2000,7 +2007,9 @@
     }
 
     public void releaseReadBackBuffer(RTTexture rtt) {
-        // NOP.
+        // This will be needed when we track LCD buffer locks and uses.
+        // (See RT-29488)
+//        context.releaseLCDBuffer();
     }
 
 }
--- a/prism-ps/src/com/sun/prism/impl/ps/CachingShapeRep.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-ps/src/com/sun/prism/impl/ps/CachingShapeRep.java	Tue Apr 09 09:33:44 2013 -0700
@@ -289,6 +289,12 @@
 
                 if (entryMatches(entry, shape, stroke, xform))
                 {
+                    entry.texData.maskTex.lock();
+                    if (entry.texData.maskTex.isSurfaceLost()) {
+                        // Eventually refcount will go to zero and entry will be freed
+                        entry.texData.maskTex.unlock();
+                        continue;
+                    }
                     // increment ref count for the chosen entry and
                     // link the given texData to it
                     entry.refCount++;
@@ -313,6 +319,7 @@
             texData.maskTex =
                 context.getResourceFactory().createMaskTexture(mw, mh, WrapMode.CLAMP_TO_ZERO);
             maskData.uploadToTexture(texData.maskTex, 0, 0, false);
+            texData.maskTex.contentsUseful();
 
             // add the new mask texture to the cache; note that we copy the
             // shape and transform so that dependents are not affected
@@ -432,6 +439,14 @@
             }
         }
 
+        if (texData.cacheEntry != null) {
+            texData.maskTex.lock();
+            if (texData.maskTex.isSurfaceLost()) {
+                texData.maskTex.unlock();
+                invalidateMaskTexData();
+            }
+        }
+
         RectBounds xformBounds = null;
         boolean boundsCopy = false;
 
@@ -545,6 +560,7 @@
             VertexBuffer vb = context.getVertexBuffer();
             vb.addQuad(dx1, dy1, dx2, dy2, tx1, ty1, tx2, ty2);
         }
+        maskTex.unlock();
     }
 
     void dispose() {
--- a/prism-ps/src/com/sun/prism/impl/ps/PaintHelper.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-ps/src/com/sun/prism/impl/ps/PaintHelper.java	Tue Apr 09 09:33:44 2013 -0700
@@ -119,11 +119,21 @@
                 PixelFormat.BYTE_BGRA_PRE, Usage.DEFAULT, WrapMode.CLAMP_TO_EDGE,
                 MULTI_TEXTURE_SIZE, MULTI_CACHE_SIZE);
         gradientCacheTexture.setLinearFiltering(true);
+        // gradientCacheTexture remains permanently locked, useful, and permanent
+        // an additional lock is added when a caller calls getGreientTeture for
+        // them to unlock
+        gradientCacheTexture.contentsUseful();
+        gradientCacheTexture.makePermanent();
 
         gtexCacheTexture = g.getResourceFactory().createTexture(
                 PixelFormat.BYTE_BGRA_PRE, Usage.DEFAULT, WrapMode.CLAMP_NOT_NEEDED,
                 GTEX_CLR_TABLE_MIRRORED_SIZE, MULTI_CACHE_SIZE);
         gtexCacheTexture.setLinearFiltering(true);
+        // gtexCacheTexture remains permanently locked, useful, and permanent
+        // an additional lock is added when a caller calls getWrapGreientTeture for
+        // them to unlock
+        gtexCacheTexture.contentsUseful();
+        gtexCacheTexture.makePermanent();
     }
 
     static Texture getGradientTexture(ShaderGraphics g, Gradient paint) {
@@ -131,6 +141,11 @@
             initGradientTextures(g);
         }
 
+        // gradientCacheTexture is left permanent and locked so it never
+        // goes away or needs to be checked for isSurfaceLost(), but we
+        // add a lock here so that the caller can unlock without knowing
+        // our inner implementation details
+        gradientCacheTexture.lock();
         return gradientCacheTexture;
     }
 
@@ -139,6 +154,11 @@
             initGradientTextures(g);
         }
 
+        // gtexCacheTexture is left permanent and locked so it never
+        // goes away or needs to be checked for isSurfaceLost(), but we
+        // add a lock here so that the caller can unlock without knowing
+        // our inner implementation details
+        gtexCacheTexture.lock();
         return gtexCacheTexture;
     }
 
@@ -242,6 +262,9 @@
             long nextOffset = ++cacheOffset;
             paint.setGradientOffset(nextOffset);
             int cacheIdx = (int)(nextOffset % MULTI_CACHE_SIZE);
+            // both gradientCacheTexture and gtexCacheTexture should be
+            // left permanent and locked so we can always call update on
+            // either or both of them here.
             gradientCacheTexture.update(colorsImg, 0, cacheIdx);
             gtexCacheTexture.update(gtexImg, 0, cacheIdx);
             return cacheIdx;
@@ -721,6 +744,7 @@
         float ch = paintTex.getContentHeight();
         float texw = paintTex.getPhysicalWidth();
         float texh = paintTex.getPhysicalHeight();
+        paintTex.unlock();
 
         // calculate plane equation constants
         Affine3D at = scratchXform3D;
--- a/prism-sw-native/include/PiscesRenderer.h	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-sw-native/include/PiscesRenderer.h	Tue Apr 09 09:33:44 2013 -0700
@@ -212,6 +212,9 @@
      */
     jint _compositeRule;
 
+    jfloat _gamma;
+    jfloat _invgamma;
+
     Surface* _surface;
 
     // Image layout
--- a/prism-sw-native/include/PiscesRenderer.inl	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-sw-native/include/PiscesRenderer.inl	Tue Apr 09 09:33:44 2013 -0700
@@ -381,6 +381,13 @@
 }
 
 static INLINE void
+renderer_setGamma(Renderer* rdr, jfloat gamma, jfloat invgamma)
+{
+    rdr->_gamma = gamma;
+    rdr->_invgamma = invgamma;
+}
+
+static INLINE void
 renderer_setMask(Renderer* rdr, jint maskType, jbyte* data, jint width, jint height, jboolean freeData)
 {
     if (rdr->_mask_free == JNI_TRUE) {
--- a/prism-sw-native/src/JPiscesRenderer.c	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-sw-native/src/JPiscesRenderer.c	Tue Apr 09 09:33:44 2013 -0700
@@ -52,7 +52,9 @@
 static int toPiscesCoords(unsigned int ff);
 static void renderer_finalize(JNIEnv *env, jobject objectHandle);
 static void fillAlphaMask(Renderer* rdr, jint minX, jint minY, jint maxX, jint maxY,
-    JNIEnv *env, jobject this, jint maskType, jbyteArray jmask, jint x, jint y, jint maskWidth, jint maskHeight, jint offset, jint stride);
+    JNIEnv *env, jobject this, jint maskType, jbyteArray jmask, jint x, jint y, jint maskWidth, jint maskHeight,
+    jint offset, jint stride,
+    jfloat gamma, jfloat invgamma);
 
 JNIEXPORT void JNICALL
 Java_com_sun_pisces_PiscesRenderer_initialize(JNIEnv* env,
@@ -713,7 +715,7 @@
     maskOffset = offset + (minY - y) * maskWidth + minX - x;
     
     fillAlphaMask(rdr, minX, minY, maxX, maxY, env, this, ALPHA_MASK, jmask,
-        x, y, maskWidth, maskHeight, maskOffset, stride);
+        x, y, maskWidth, maskHeight, maskOffset, stride, 1, 1);
 }
 
 /*
@@ -722,7 +724,9 @@
  * Signature: ([BIIIIII)V
  */
 JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_fillLCDAlphaMaskImpl
-(JNIEnv *env, jobject this, jbyteArray jmask, jint x, jint y, jint maskWidth, jint maskHeight, jint offset, jint stride)
+(JNIEnv *env, jobject this, jbyteArray jmask, jint x, jint y, jint maskWidth, jint maskHeight,
+    jint offset, jint stride,
+    jfloat gamma, jfloat invgamma)
 {
     Renderer* rdr;
     jint minX, minY, maxX, maxY;
@@ -737,12 +741,13 @@
     maskOffset = offset + (minY - y) * maskWidth + (minX - x) * 3;
     
     fillAlphaMask(rdr, minX, minY, maxX, maxY, env, this, LCD_ALPHA_MASK, jmask,
-        x, y, maskWidth, maskHeight, maskOffset, stride);
+        x, y, maskWidth, maskHeight, maskOffset, stride, gamma, invgamma);
 }
 
 static void fillAlphaMask(Renderer* rdr, jint minX, jint minY, jint maxX, jint maxY,
     JNIEnv *env, jobject this, jint maskType, jbyteArray jmask, 
-    jint x, jint y, jint maskWidth, jint maskHeight, jint offset, jint stride)
+    jint x, jint y, jint maskWidth, jint maskHeight, jint offset, jint stride,
+    jfloat gamma, jfloat invgamma)
 {
     jint rowsToBeRendered, rowsBeingRendered;
     
@@ -762,6 +767,7 @@
             jint height = maxY - minY + 1;
 
             renderer_setMask(rdr, maskType, mask, maskWidth, maskHeight, JNI_FALSE);
+            renderer_setGamma(rdr, gamma, invgamma);
 
             INVALIDATE_RENDERER_SURFACE(rdr);
             VALIDATE_BLITTING(rdr);
--- a/prism-sw-native/src/PiscesBlit.c	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-sw-native/src/PiscesBlit.c	Tue Apr 09 09:33:44 2013 -0700
@@ -44,7 +44,8 @@
                                  jint sgreen, jint sblue);
 
 static INLINE void blendLCDSrcOver8888_pre(jint *intData,
-    jint ared, jint agreen, jint ablue, jint sred, jint sgreen, jint sblue);
+    jint ared, jint agreen, jint ablue, jint sred, jint sgreen, jint sblue,
+    jfloat gamma, jfloat invgamma);
 
 static INLINE void blendSrc8888(jint *intData, jint aval, jint aaval,
                          jint sred, jint sgreen, jint sblue);
@@ -1124,6 +1125,9 @@
     jint cgreen = rdr->_cgreen;
     jint cblue = rdr->_cblue;
 
+    jfloat gamma = rdr->_gamma;
+    jfloat invgamma = rdr->_invgamma;
+
     minX = rdr->_minTouched;
     maxX = rdr->_maxTouched;
     w = (maxX >= minX) ? (maxX - minX + 1) : 0;
@@ -1146,7 +1150,9 @@
             if (aval_ismax == MAX_ALPHA) {
                 intData[iidx] = 0xff000000 | (cred << 16) | (cgreen << 8) | cblue;
             } else {
-                blendLCDSrcOver8888_pre(&intData[iidx], ared, agreen, ablue, cred, cgreen, cblue);
+                blendLCDSrcOver8888_pre(&intData[iidx], ared, agreen, ablue,
+                    cred, cgreen, cblue,
+                    gamma, invgamma);
             }
             iidx += imagePixelStride;
         }
@@ -1543,7 +1549,8 @@
 static void
 blendLCDSrcOver8888_pre(jint *intData,
                              jint ared, jint agreen, jint ablue,
-                             jint sred, jint sgreen, jint sblue)
+                             jint sred, jint sgreen, jint sblue,
+                             jfloat gamma, jfloat invgamma)
 {
     jint ival = *intData;
     //destination alpha
@@ -1552,11 +1559,21 @@
     jint dred = (ival >> 16) & 0xff;
     jint dgreen = (ival >> 8) & 0xff;
     jint dblue = ival & 0xff;
-    
-    jint ored    = div255(ared * sred     + (255 - ared) * dred);
-    jint ogreen  = div255(agreen * sgreen + (255 - agreen) * dgreen);
-    jint oblue   = div255(ablue * sblue   + (255 - ablue) * dblue);
-    
+
+    jint ored, ogreen, oblue;
+
+    dred = (jint) (255 * (pow(dred / 255.0, invgamma)));
+    dgreen = (jint) (255 * (pow(dgreen / 255.0, invgamma)));
+    dblue = (jint) (255 * (pow(dblue / 255.0, invgamma)));
+
+    ored    = ared * sred     + (255 - ared) * dred;
+    ogreen  = agreen * sgreen + (255 - agreen) * dgreen;
+    oblue   = ablue * sblue   + (255 - ablue) * dblue;
+
+    ored = (jint) (255 * (pow(ored / 65025.0, gamma)));    // 65025 = 255*255
+    ogreen = (jint) (255 * (pow(ogreen / 65025.0, gamma)));
+    oblue = (jint) (255 * (pow(oblue / 65025.0, gamma)));
+
     *intData = 0xFF000000 | (ored << 16) | (ogreen << 8) | oblue;
 }
 
--- a/prism-sw/src/com/sun/pisces/PiscesRenderer.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-sw/src/com/sun/pisces/PiscesRenderer.java	Tue Apr 09 09:33:44 2013 -0700
@@ -327,12 +327,15 @@
 
     private native void fillAlphaMaskImpl(byte[] mask, int x, int y, int width, int height, int offset, int stride);
 
-    public void fillLCDAlphaMask(byte[] mask, int x, int y, int width, int height, int offset, int stride) {
+    public void fillLCDAlphaMask(byte[] mask, int x, int y, int width, int height, int offset, int stride,
+                                 float gamma, float invgamma)
+    {
         this.inputImageCheck(width, height, offset, stride, mask.length);
-        this.fillLCDAlphaMaskImpl(mask, x, y, width, height, offset, stride);
+        this.fillLCDAlphaMaskImpl(mask, x, y, width, height, offset, stride, gamma, invgamma);
     }
 
-    private native void fillLCDAlphaMaskImpl(byte[] mask, int x, int y, int width, int height, int offset, int stride);
+    private native void fillLCDAlphaMaskImpl(byte[] mask, int x, int y, int width, int height, int offset, int stride,
+        float gamma, float invgamma);
 
     public void drawImage(int imageType, int data[],  int width, int height, int offset, int stride,
         Transform6 textureTransform, boolean repeat,
--- a/prism-sw/src/com/sun/prism/sw/SWGraphics.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-sw/src/com/sun/prism/sw/SWGraphics.java	Tue Apr 09 09:33:44 2013 -0700
@@ -29,6 +29,7 @@
 import com.sun.javafx.font.FontResource;
 import com.sun.javafx.font.FontStrike;
 import com.sun.javafx.font.Metrics;
+import com.sun.javafx.font.PrismFontUtils;
 import com.sun.javafx.scene.text.GlyphList;
 import com.sun.javafx.geom.Ellipse2D;
 import com.sun.javafx.geom.Line2D;
@@ -317,12 +318,16 @@
     }
 
     private void setPaintBeforeDraw(float x, float y, float width, float height) {
-        switch (paint.getType()) {
+        this.setPaintBeforeDraw(this.paint, x, y, width, height);
+    }
+
+    private void setPaintBeforeDraw(Paint p, float x, float y, float width, float height) {
+        switch (p.getType()) {
             case COLOR:
-                this.setColor((Color)this.paint, this.compositeAlpha);
+                this.setColor((Color)p, this.compositeAlpha);
                 break;
             case LINEAR_GRADIENT:
-                final LinearGradient lg = (LinearGradient)this.paint;
+                final LinearGradient lg = (LinearGradient)p;
                 if (PrismSettings.debug) {
                     System.out.println("PR.setLinearGradient: " + lg.getX1() + ", " + lg.getY1() + ", " + lg.getX2() + ", " + lg.getY2());
                 }
@@ -336,7 +341,7 @@
                     getFractions(lg), getARGB(lg, this.compositeAlpha), getPiscesGradientCycleMethod(lg.getSpreadMethod()), piscesTx);
                 break;
             case RADIAL_GRADIENT:
-                final RadialGradient rg = (RadialGradient)this.paint;
+                final RadialGradient rg = (RadialGradient)p;
                 if (PrismSettings.debug) {
                     System.out.println("PR.setRadialGradient: " + rg.getCenterX() + ", " + rg.getCenterY() + ", " + rg.getFocusAngle() + ", " + rg.getFocusDistance() + ", " + rg.getRadius());
                 }
@@ -352,7 +357,7 @@
                         getFractions(rg), getARGB(rg, this.compositeAlpha), getPiscesGradientCycleMethod(rg.getSpreadMethod()), piscesTx);
                 break;
             case IMAGE_PATTERN:
-                final ImagePattern ip = (ImagePattern)this.paint;
+                final ImagePattern ip = (ImagePattern)p;
                 final Image image = ip.getImage();
                 if (PrismSettings.debug) {
                     System.out.println("PR.setTexturePaint: " + image);
@@ -386,7 +391,7 @@
                 }
                 break;
             default:
-                throw new IllegalArgumentException("Unknown paint type: " + paint.getType());
+                throw new IllegalArgumentException("Unknown paint type: " + p.getType());
         }
     }
 
@@ -724,37 +729,49 @@
 
         // check for selection that is out of range of this line (TextArea)
         if ((selectGlyphStart < 0 && selectGlyphEnd < 0)||(selectGlyphStart >= gl.getGlyphCount() && selectGlyphEnd >= gl.getGlyphCount())) {
-            this.setPaintBeforeDraw(bx, by, bw, bh);
-            this.drawStringInternal(gl, strike, x, y, 0, gl.getGlyphCount());
+            this.drawStringInternal(gl, strike, x, y, 0, gl.getGlyphCount(), this.paint, bx, by, bw, bh);
         } else {
             float advanceX = 0;
             if (selectGlyphStart > 0) {
-                this.setPaintBeforeDraw(bx, by, bw, bh);
-                advanceX = this.drawStringInternal(gl, strike, x, y, 0, selectGlyphStart);
+                advanceX = this.drawStringInternal(gl, strike, x, y, 0, selectGlyphStart, this.paint, bx, by, bw, bh);
             }
-            this.setColor(selectColor, this.compositeAlpha);
             advanceX += this.drawStringInternal(gl, strike, x+advanceX, y,
-                                                Math.max(0, selectGlyphStart), Math.min(gl.getGlyphCount(), selectGlyphEnd));
+                                                Math.max(0, selectGlyphStart), Math.min(gl.getGlyphCount(), selectGlyphEnd),
+                                                selectColor, 0, 0, 0, 0);
             if (selectGlyphEnd < gl.getGlyphCount()) {
-                this.setPaintBeforeDraw(bx, by, bw, bh);
-                this.drawStringInternal(gl, strike, x+advanceX, y, selectGlyphEnd, gl.getGlyphCount());
+                this.drawStringInternal(gl, strike, x+advanceX, y, selectGlyphEnd, gl.getGlyphCount(),
+                                        this.paint, bx, by, bw, bh);
             }
         }
     }
 
-    private float drawStringInternal(GlyphList gl, FontStrike strike, float x, float y, int strFrom, int strTo) {
+    private float drawStringInternal(GlyphList gl, FontStrike strike, float x, float y, int strFrom, int strTo,
+                                     Paint p, float bx, float by, float bw, float bh)
+    {
         float advanceX = 0;
         if (tx.isTranslateOrIdentity() && strike.supportsGlyphImages() && (!strike.drawAsShapes())) {
             final boolean doLCDText = (strike.getAAMode() == FontResource.AA_LCD) &&
                     getRenderTarget().isOpaque() &&
-                    (paint.getType() == Paint.Type.COLOR) &&
+                    (p.getType() == Paint.Type.COLOR) &&
                     tx.is2D();
 
-            if (!doLCDText) {
+            final float gamma, invgamma;
+            if (doLCDText) {
+                invgamma = PrismFontUtils.getLCDContrast();
+                gamma = 1.0f/invgamma;
+                final Color c = (Color)p;
+                final Color correctedColor = new Color((float)Math.pow(c.getRed(), invgamma),
+                                                       (float)Math.pow(c.getGreen(), invgamma),
+                                                       (float)Math.pow(c.getBlue(), invgamma),
+                                                       (float)Math.pow(c.getAlpha(), invgamma));
+                this.setColor(correctedColor, this.compositeAlpha);
+            } else {
+                gamma = invgamma = 0;
                 final FontResource fr = strike.getFontResource();
                 final float origSize = strike.getSize();
                 final BaseTransform origTx = strike.getTransform();
                 strike = fr.getStrike(origSize, origTx, FontResource.AA_GREYSCALE);
+                this.setPaintBeforeDraw(p, bx, by, bw, bh);
             }
 
             for (int i = strFrom; i < strTo; i++) {
@@ -764,7 +781,8 @@
                             (int)(x + tx.getMxt() + g.getOriginX() + gl.getPosX(i) + 0.5f),
                             (int)(y + tx.getMyt() + g.getOriginY() + gl.getPosY(i) + 0.5f),
                             g.getWidth(), g.getHeight(),
-                            0, g.getWidth());
+                            0, g.getWidth(),
+                            gamma, invgamma);
                 } else {
                     this.pr.fillAlphaMask(g.getPixelData(),
                             (int)(x + tx.getMxt() + g.getOriginX() + gl.getPosX(i) + 0.5f),
--- a/prism-sw/src/com/sun/prism/sw/SWPresentable.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-sw/src/com/sun/prism/sw/SWPresentable.java	Tue Apr 09 09:33:44 2013 -0700
@@ -46,6 +46,10 @@
         this.pState = pState;
     }
 
+    public boolean lockResources() {
+        return false;
+    }
+
     public boolean prepare(Rectangle dirtyregion) {
         if (!pState.isViewClosed()) {
             /*
--- a/prism-sw/src/com/sun/prism/sw/SWResourceFactory.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-sw/src/com/sun/prism/sw/SWResourceFactory.java	Tue Apr 09 09:33:44 2013 -0700
@@ -39,6 +39,7 @@
 import com.sun.prism.impl.BaseRenderingContext;
 import com.sun.prism.impl.BaseResourceFactory;
 import com.sun.prism.impl.PrismSettings;
+import com.sun.prism.impl.TextureResourcePool;
 import com.sun.prism.impl.VertexBuffer;
 import com.sun.prism.impl.shape.BasicRoundRectRep;
 import com.sun.prism.impl.shape.BasicShapeRep;
@@ -58,7 +59,11 @@
         this.screen = screen;
         this.context = new SWContext(this);
     }
-    
+
+    public TextureResourcePool getTextureResourcePool() {
+        return SWTexturePool.instance;
+    }
+
     public Screen getScreen() {
         return screen;
     }
@@ -105,6 +110,11 @@
     @Override public RTTexture createRTTexture(int width, int height,
                                                WrapMode wrapMode)
     {
+        SWTexturePool pool = SWTexturePool.instance;
+        long size = pool.estimateRTTextureSize(width, height, false);
+        if (!pool.prepareForAllocation(size)) {
+            return null;
+        }
         return new SWRTTexture(this, width, height);
     }
 
@@ -137,6 +147,11 @@
                                            WrapMode wrapMode,
                                            int w, int h)
     {
+        SWTexturePool pool = SWTexturePool.instance;
+        long size = pool.estimateTextureSize(w, h, formatHint);
+        if (!pool.prepareForAllocation(size)) {
+            return null;
+        }
         return SWTexture.create(this, formatHint, wrapMode, w, h);
     }
 }
--- a/prism-sw/src/com/sun/prism/sw/SWTexture.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/prism-sw/src/com/sun/prism/sw/SWTexture.java	Tue Apr 09 09:33:44 2013 -0700
@@ -67,6 +67,7 @@
         height = h;
         stride = w;
         offset = 0;
+        lock();
     }
 
     SWTexture(SWTexture sharedTex, WrapMode altMode) {
@@ -77,6 +78,9 @@
         // REMIND: Use indirection to share the serial number?
         this.lastImageSerial = sharedTex.lastImageSerial;
         this.wrapMode = altMode;
+        // The lock is transferred to this texture...
+        sharedTex.unlock();
+        lock();
     }
 
     SWResourceFactory getResourceFactory() {
@@ -91,6 +95,52 @@
         return offset;
     }
 
+    private int lockcount;
+    public void lock() {
+        lockcount++;
+    }
+
+    public void unlock() {
+        assertLocked();
+        lockcount--;
+    }
+
+    public boolean isLocked() {
+        return (lockcount > 0);
+    }
+
+    public int getLockCount() {
+        return lockcount;
+    }
+
+    public void assertLocked() {
+        if (lockcount <= 0) {
+            throw new IllegalStateException("texture not locked");
+        }
+    }
+
+    boolean permanent;
+    public void makePermanent() {
+        permanent = true;
+    }
+
+    int employcount;
+    public void contentsUseful() {
+        assertLocked();
+        employcount++;
+    }
+
+    public void contentsNotUseful() {
+        if (employcount <= 0) {
+            throw new IllegalStateException("Resource obsoleted too many times");
+        }
+        employcount--;
+    }
+
+    public boolean isSurfaceLost() {
+        return false;
+    }
+
     @Override
     public void dispose() { }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prism-sw/src/com/sun/prism/sw/SWTexturePool.java	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.prism.sw;
+
+import com.sun.prism.PixelFormat;
+import com.sun.prism.impl.BaseResourcePool;
+import com.sun.prism.impl.PrismSettings;
+import com.sun.prism.impl.TextureResourcePool;
+
+class SWTexturePool extends BaseResourcePool<SWTexture>
+    implements TextureResourcePool<SWTexture>
+{
+    static final SWTexturePool instance = new SWTexturePool();
+
+    private static long maxVram() {
+        long heapmax = Runtime.getRuntime().maxMemory();
+        long setmax = PrismSettings.maxVram;
+        return Math.min(heapmax / 4, setmax);
+    }
+
+    final long targetVram;
+
+    private SWTexturePool() {
+        super(null, maxVram());
+        targetVram = Math.min(max() / 2, PrismSettings.targetVram);
+    }
+
+    public long target() {
+        return targetVram;
+    }
+
+    @Override
+    public long used() {
+//        long heapfree = Runtime.getRuntime().freeMemory();
+//        long managedfree = max() - managed();
+//        return max() - Math.min(heapfree, managedfree);
+        return 0;
+    }
+
+    public long size(SWTexture resource) {
+        long size = resource.getPhysicalWidth();
+        size *= resource.getPhysicalHeight();
+        if (resource instanceof SWArgbPreTexture) {
+            size *= 4L;
+        }
+        return size;
+    }
+
+    public long estimateTextureSize(int width, int height, PixelFormat format) {
+        switch (format) {
+            case BYTE_ALPHA:
+                return ((long) width) * ((long) height);
+            default:
+                return ((long) width) * ((long) height) * 4L;
+        }
+    }
+
+    public long estimateRTTextureSize(int width, int height, boolean hasDepth) {
+        return ((long) width) * ((long) height) * 4L;
+    }
+}
--- a/settings.gradle	Thu Apr 04 20:11:19 2013 -0700
+++ b/settings.gradle	Tue Apr 09 09:33:44 2013 -0700
@@ -1,14 +1,14 @@
-include 'build-tools', 'base', 'graphics', 'controls', 'swing', 'swt', /*'web',*/ 'fxml' /*, 'media'*/, 'designTime',
-        /*'graphics:native',*/ 'graphics:effects-jsl', 'graphics:prism-jsl'
-project(':base').projectDir = file('modules/base')
-project(':graphics').projectDir = file('modules/graphics')
-//project(':graphics:native').projectDir = file('modules/graphics/native')
-project(':graphics:effects-jsl').projectDir = file('modules/graphics/effects-jsl')
-project(':graphics:prism-jsl').projectDir = file('modules/graphics/prism-jsl')
-project(':controls').projectDir = file('modules/controls')
-project(':swing').projectDir = file('modules/swing')
-project(':swt').projectDir = file('modules/swt')
-/*project(':media').projectDir = file('modules/media')*/
-//project(':web').projectDir = file('modules/web')
-project(':fxml').projectDir = file('modules/fxml')
-project(':designTime').projectDir = file('modules/designTime')
+include "build-tools", "base", "graphics", "controls", "swing", "swt", "fxml", "designTime",
+        "graphics:effects-jsl", "graphics:prism-jsl",
+        "fxpackager"
+
+project(":base").projectDir = file("modules/base")
+project(":graphics").projectDir = file("modules/graphics")
+project(":graphics:effects-jsl").projectDir = file("modules/graphics/effects-jsl")
+project(":graphics:prism-jsl").projectDir = file("modules/graphics/prism-jsl")
+project(":controls").projectDir = file("modules/controls")
+project(":swing").projectDir = file("modules/swing")
+project(":swt").projectDir = file("modules/swt")
+project(":fxml").projectDir = file("modules/fxml")
+project(":designTime").projectDir = file("modules/designTime")
+project(":fxpackager").projectDir = file("modules/fxpackager")
--- a/test-stub-toolkit/src/com/sun/javafx/pgstub/StubFilterable.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/test-stub-toolkit/src/com/sun/javafx/pgstub/StubFilterable.java	Tue Apr 09 09:33:44 2013 -0700
@@ -71,4 +71,16 @@
     public void flush() {
     }
 
+    @Override
+    public void lock() {
+    }
+
+    @Override
+    public void unlock() {
+    }
+
+    @Override
+    public boolean isLost() {
+        return false;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-stub-toolkit/src/com/sun/javafx/pgstub/StubParallelCamera.java	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.pgstub;
+
+import com.sun.javafx.geom.BaseBounds;
+import com.sun.javafx.geom.Rectangle;
+import com.sun.javafx.geom.transform.Affine3D;
+import com.sun.javafx.geom.transform.BaseTransform;
+import com.sun.javafx.geom.transform.GeneralTransform3D;
+import com.sun.javafx.sg.PGNode;
+import com.sun.javafx.sg.PGParallelCamera;
+import com.sun.scenario.effect.Blend;
+
+public class StubParallelCamera extends StubNode implements PGParallelCamera {
+    @Override public GeneralTransform3D getScreenProjViewTx(GeneralTransform3D tx, double w, double h) { return null; }
+    @Override public Rectangle getViewport(Rectangle vp) { return null; }
+    @Override public void setNearClip(float f) {}
+    @Override public void setFarClip(float f) {}
+    @Override public void setWorldTransform(Affine3D ad) {}
+    @Override public void setTransformMatrix(BaseTransform bt) {}
+    @Override public void setContentBounds(BaseBounds bb) {}
+    @Override public void setTransformedBounds(BaseBounds bb, boolean bln) {}
+    @Override public void setVisible(boolean bln) {}
+    @Override public void setOpacity(float f) {}
+    @Override public void setNodeBlendMode(Blend.Mode mode) {}
+    @Override public void setDepthTest(boolean bln) {}
+    @Override public void setClipNode(PGNode pgnode) {}
+    @Override public void setCachedAsBitmap(boolean bln, CacheHint ch) {}
+    @Override public void setEffect(Object o) {}
+    @Override public void effectChanged() {}
+    @Override public void release() {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-stub-toolkit/src/com/sun/javafx/pgstub/StubPerspectiveCamera.java	Tue Apr 09 09:33:44 2013 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.pgstub;
+
+import com.sun.javafx.geom.BaseBounds;
+import com.sun.javafx.geom.Rectangle;
+import com.sun.javafx.geom.transform.Affine3D;
+import com.sun.javafx.geom.transform.BaseTransform;
+import com.sun.javafx.geom.transform.GeneralTransform3D;
+import com.sun.javafx.sg.PGNode;
+import com.sun.javafx.sg.PGPerspectiveCamera;
+import com.sun.scenario.effect.Blend;
+
+public class StubPerspectiveCamera extends StubNode implements PGPerspectiveCamera{
+    @Override public GeneralTransform3D getScreenProjViewTx(GeneralTransform3D tx, double w, double h) { return null; }
+    @Override public Rectangle getViewport(Rectangle vp) { return null; }
+    @Override public void setFieldOfView(float f) {}
+    @Override public void setVerticalFieldOfView(boolean bln) {}
+    @Override public void setNearClip(float f) {}
+    @Override public void setFarClip(float f) {}
+    @Override public void setWorldTransform(Affine3D ad) {}
+    @Override public void setTransformMatrix(BaseTransform bt) {}
+    @Override public void setContentBounds(BaseBounds bb) {}
+    @Override public void setTransformedBounds(BaseBounds bb, boolean bln) {}
+    @Override public void setVisible(boolean bln) {}
+    @Override public void setOpacity(float f) {}
+    @Override public void setNodeBlendMode(Blend.Mode mode) {}
+    @Override public void setDepthTest(boolean bln) {}
+    @Override public void setClipNode(PGNode pgnode) {}
+    @Override public void setCachedAsBitmap(boolean bln, PGNode.CacheHint ch) {}
+    @Override public void setEffect(Object o) {}
+    @Override public void effectChanged() {}
+    @Override public void release() {}
+}
--- a/test-stub-toolkit/src/com/sun/javafx/pgstub/StubToolkit.java	Thu Apr 04 20:11:19 2013 -0700
+++ b/test-stub-toolkit/src/com/sun/javafx/pgstub/StubToolkit.java	Tue Apr 09 09:33:44 2013 -0700
@@ -883,50 +883,12 @@
 
     @Override
     public PGParallelCamera createPGParallelCamera() {
-        return new PGParallelCamera() {
-            @Override public GeneralTransform3D getScreenProjViewTx(GeneralTransform3D tx, double w, double h) { return null; }
-            @Override public Rectangle getViewport(Rectangle vp) { return null; }
-            @Override public void setNearClip(float f) {}
-            @Override public void setFarClip(float f) {}
-            @Override public void setWorldTransform(Affine3D ad) {}
-            @Override public void setTransformMatrix(BaseTransform bt) {}
-            @Override public void setContentBounds(BaseBounds bb) {}
-            @Override public void setTransformedBounds(BaseBounds bb, boolean bln) {}
-            @Override public void setVisible(boolean bln) {}
-            @Override public void setOpacity(float f) {}
-            @Override public void setNodeBlendMode(Mode mode) {}
-            @Override public void setDepthTest(boolean bln) {}
-            @Override public void setClipNode(PGNode pgnode) {}
-            @Override public void setCachedAsBitmap(boolean bln, CacheHint ch) {}
-            @Override public void setEffect(Object o) {}
-            @Override public void effectChanged() {}
-            @Override public void release() {}
-        };
+        return new StubParallelCamera();
     }
 
     @Override
     public PGPerspectiveCamera createPGPerspectiveCamera(boolean fixedEyePosition) {
-        return new PGPerspectiveCamera() {
-            @Override public GeneralTransform3D getScreenProjViewTx(GeneralTransform3D tx, double w, double h) { return null; }
-            @Override public Rectangle getViewport(Rectangle vp) { return null; }
-            @Override public void setFieldOfView(float f) {}
-            @Override public void setVerticalFieldOfView(boolean bln) {}
-            @Override public void setNearClip(float f) {}
-            @Override public void setFarClip(float f) {}
-            @Override public void setWorldTransform(Affine3D ad) {}
-            @Override public void setTransformMatrix(BaseTransform bt) {}
-            @Override public void setContentBounds(BaseBounds bb) {}
-            @Override public void setTransformedBounds(BaseBounds bb, boolean bln) {}
-            @Override public void setVisible(boolean bln) {}
-            @Override public void setOpacity(float f) {}
-            @Override public void setNodeBlendMode(Mode mode) {}
-            @Override public void setDepthTest(boolean bln) {}
-            @Override public void setClipNode(PGNode pgnode) {}
-            @Override public void setCachedAsBitmap(boolean bln, CacheHint ch) {}
-            @Override public void setEffect(Object o) {}
-            @Override public void effectChanged() {}
-            @Override public void release() {}
-        };
+        return new StubPerspectiveCamera();
     }
 
     @Override
--- a/win.gradle	Thu Apr 04 20:11:19 2013 -0700
+++ b/win.gradle	Tue Apr 09 09:33:44 2013 -0700
@@ -107,3 +107,4 @@
 defineProperty("LINK", "$WINDOWS_VS_VSINSTALLDIR/VC/BIN/link.exe");
 defineProperty("RC", "$WINDOWS_SDK_DIR/Bin/RC.Exe");
 defineProperty("FXC", "$WINDOWS_DXSDK_DIR/utilities/bin/x86/fxc");
+defineProperty("MT", "$WINDOWS_SDK_DIR/Bin/mt.exe");