harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mloe...@apache.org
Subject svn commit: r440748 [7/25] - in /incubator/harmony/enhanced/classlib/trunk/modules: accessibility/src/main/java/javax/accessibility/ awt/ awt/make/ awt/src/main/java/common/java/awt/ awt/src/main/java/common/java/awt/datatransfer/ awt/src/main/java/com...
Date Wed, 06 Sep 2006 16:06:30 GMT
Added: incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLBlitter.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLBlitter.java?view=auto&rev=440748
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLBlitter.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLBlitter.java Wed Sep  6 09:06:15 2006
@@ -0,0 +1,653 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package org.apache.harmony.awt.gl.opengl;
+
+import org.apache.harmony.awt.gl.render.Blitter;
+import org.apache.harmony.awt.gl.*;
+import org.apache.harmony.awt.nativebridge.NativeBridge;
+import org.apache.harmony.awt.nativebridge.Int32Pointer;
+import org.apache.harmony.misc.accessors.LockedArray;
+
+import java.awt.geom.AffineTransform;
+import java.awt.*;
+import java.awt.image.ColorModel;
+import java.awt.image.BufferedImage;
+
+public class OGLBlitter implements Blitter {
+    private static final GL gl = GL.getInstance();
+
+    private static final OGLBlitter inst = new OGLBlitter();
+
+    private static final class OGLImageParams {
+        OGLImageParams(
+                int format, int intFormat,
+                int type, int alignment,
+                boolean requiresConversion
+        ) {
+            oglFormat = format;
+            oglIntFormat = intFormat;
+            oglType = type;
+            oglAlignment = alignment;
+            this.requiresConversion = requiresConversion;
+        }
+
+        int oglFormat;
+        int oglIntFormat;
+        int oglType;
+        int oglAlignment;
+        boolean requiresConversion;
+    }
+
+    static final class OGLTextureParams {
+        OGLTextureParams(int tName, int p2w, int p2h, int w, int h) {
+            textureName = tName;
+            this.p2w = p2w;
+            this.p2h = p2h;
+            width = w;
+            height = h;
+        }
+
+        int textureName;
+
+        // Actual texture width and height
+        int p2w;
+        int p2h;
+
+        // Size of the used part of the texture
+        int width;
+        int height;
+
+        final void deleteTexture() {
+            deleteTexture(textureName);
+            textureName = 0;
+        }
+
+        static final void deleteTexture(int textureName) {
+            if (textureName != 0) {
+                Int32Pointer texPtr =
+                        NativeBridge.getInstance().createInt32Pointer(1, true);
+                texPtr.set(0, textureName);
+                gl.glDeleteTextures(1, texPtr);
+                texPtr.free();
+            }
+        }
+    };
+
+    private static final OGLImageParams IMAGE_TYPE_MAPPING[] = new OGLImageParams [] {
+        new OGLImageParams(GLDefs.GL_BGRA, 4, GLDefs.GL_UNSIGNED_INT_8_8_8_8_REV, 4, true), // TYPE_CUSTOM = 0
+        new OGLImageParams(GLDefs.GL_BGR, 3, GLDefs.GL_UNSIGNED_INT_8_8_8_8_REV, 4, false), // TYPE_INT_RGB = 1
+        new OGLImageParams(GLDefs.GL_BGRA, 4, GLDefs.GL_UNSIGNED_INT_8_8_8_8_REV, 4, false), // TYPE_INT_ARGB = 2
+        new OGLImageParams(GLDefs.GL_BGRA, 4, GLDefs.GL_UNSIGNED_INT_8_8_8_8_REV, 4, false), // TYPE_INT_ARGB_PRE = 3
+        new OGLImageParams(GLDefs.GL_RGB, 3, GLDefs.GL_UNSIGNED_INT_8_8_8_8_REV, 4, false), // TYPE_INT_BGR = 4
+        new OGLImageParams(GLDefs.GL_BGR, 3, GLDefs.GL_UNSIGNED_BYTE, 1, false), // TYPE_3BYTE_BGR = 5
+        new OGLImageParams(GLDefs.GL_RGBA, 4, GLDefs.GL_UNSIGNED_INT_8_8_8_8_REV, 4, false), // TYPE_4BYTE_ABGR = 6
+        new OGLImageParams(GLDefs.GL_RGBA, 4, GLDefs.GL_UNSIGNED_INT_8_8_8_8_REV, 4, false), // TYPE_4BYTE_ABGR_PRE = 7
+        new OGLImageParams(GLDefs.GL_RGB, 3, GLDefs.GL_UNSIGNED_SHORT_5_6_5, 2, false), // TYPE_USHORT_565_RGB = 8
+        new OGLImageParams(GLDefs.GL_BGR, 3, GLDefs.GL_UNSIGNED_SHORT_1_5_5_5_REV, 2, false), // TYPE_USHORT_555_RGB = 9
+        new OGLImageParams(GLDefs.GL_LUMINANCE, 1, GLDefs.GL_UNSIGNED_BYTE, 1, false), // TYPE_BYTE_GRAY = 10
+        new OGLImageParams(GLDefs.GL_LUMINANCE, 1, GLDefs.GL_UNSIGNED_SHORT, 2, false), // TYPE_USHORT_GRAY = 11
+        new OGLImageParams(GLDefs.GL_BGR, 3, GLDefs.GL_UNSIGNED_INT_8_8_8_8_REV, 4, true), // TYPE_BYTE_BINARY = 12
+        new OGLImageParams(GLDefs.GL_BGRA, 4, GLDefs.GL_UNSIGNED_INT_8_8_8_8_REV, 4, true) // TYPE_BYTE_INDEXED = 13
+    };
+
+    public static OGLBlitter getInstance(){
+        return inst;
+    }
+
+    public void blit(
+            int srcX, int srcY, Surface srcSurf,
+            int dstX, int dstY, Surface dstSurf,
+            int width, int height,
+            AffineTransform sysxform, AffineTransform xform,
+            Composite comp, Color bgcolor, MultiRectArea clip
+    ) {
+        int type = xform.getType();
+        switch (type) {
+            case AffineTransform.TYPE_TRANSLATION:
+                dstX += xform.getTranslateX();
+                dstY += xform.getTranslateY();
+            case AffineTransform.TYPE_IDENTITY:
+                 blit(srcX, srcY, srcSurf, dstX, dstY, dstSurf,
+                         width, height, sysxform, comp, bgcolor, clip);
+                break;
+            default:
+                AffineTransform at = (AffineTransform) sysxform.clone();
+                at.concatenate(xform);
+                blit(srcX, srcY, srcSurf, dstX, dstY, dstSurf,
+                        width, height, at, comp, bgcolor, clip);
+        }
+    }
+
+    public void blit(
+            int srcX, int srcY, Surface srcSurf,
+            int dstX, int dstY, Surface dstSurf,
+            int width, int height,
+            AffineTransform sysxform,
+            Composite comp, Color bgcolor, MultiRectArea clip
+    ) {
+        int type = sysxform.getType();
+        switch (type) {
+            case AffineTransform.TYPE_TRANSLATION:
+                dstX += sysxform.getTranslateX();
+                dstY += sysxform.getTranslateY();
+            case AffineTransform.TYPE_IDENTITY:
+                blitImpl(
+                        srcX, srcY, srcSurf,
+                        dstX, dstY, dstSurf,
+                        width, height,
+                        comp, bgcolor, clip,
+                        null
+                );
+                break;
+            default:
+                blitImpl(
+                        srcX, srcY, srcSurf,
+                        dstX, dstY, dstSurf,
+                        width, height,
+                        comp, bgcolor, clip,
+                        sysxform
+                );
+        }
+    }
+
+    public void blit(
+            int srcX, int srcY, Surface srcSurf,
+            int dstX, int dstY, Surface dstSurf,
+            int width, int height,
+            Composite comp, Color bgcolor, MultiRectArea clip
+    ) {
+        blitImpl(
+            srcX, srcY, srcSurf,
+            dstX, dstY, dstSurf,
+            width, height,
+            comp, bgcolor, clip,
+            null
+        );
+    }
+
+    private final void blitImpl(
+            int srcX, int srcY, Surface srcSurf,
+            int dstX, int dstY, Surface dstSurf,
+            int width, int height,
+            Composite comp, Color bgcolor, MultiRectArea clip,
+            AffineTransform xform
+    ) {
+        OGLSurface oglDstSurf = (OGLSurface) dstSurf;
+        OGLGraphics2D oglg = oglDstSurf.oglg;
+        oglg.makeCurrent();
+
+        // Set the requested clip, saving current clip
+        MultiRectArea oldClip = (MultiRectArea) oglg.getClip();
+        boolean needRestoreClip = false;
+        if ((clip == null && oldClip != null) || !clip.equals(oldClip)) {
+            oglg.setTransformedClip(clip);
+            needRestoreClip = true;
+        } else {
+            oldClip = null;
+        }
+
+        // Fill the background if needed
+        if (
+                srcSurf.getColorModel().getTransparency() != Transparency.OPAQUE &&
+                bgcolor != null
+        ) {
+            if (xform == null) {
+                oglg.fillRect(dstX, dstY, width, height);
+            } else {
+                Rectangle bounds = new Rectangle(srcX, srcY, width, height);
+                Shape tBounds = xform.createTransformedShape(bounds);
+                AffineTransform dstT = AffineTransform.getTranslateInstance(dstX, dstY);
+                tBounds = dstT.createTransformedShape(tBounds);
+                Color savedc = oglg.getColor();
+                oglg.setColor(bgcolor);
+                oglg.fill(tBounds);
+                oglg.setColor(savedc);
+            }
+        }
+
+        if (srcX != 0 || srcY != 0) {
+            gl.glPixelStoref(GLDefs.GL_UNPACK_SKIP_PIXELS, srcX);
+            gl.glPixelStoref(GLDefs.GL_UNPACK_SKIP_ROWS, srcY);
+        }
+
+        ColorModel srcCM = srcSurf.getColorModel();
+
+        boolean needRestoreComposite = false;
+        boolean needPremultiply = false;
+        if (comp instanceof AlphaComposite) {
+            if (
+                    !oglg.getComposite().equals(comp) ||
+                    !srcCM.isAlphaPremultiplied() ||
+                    srcCM.hasAlpha() == oglg.opaqueColor
+            ) {
+                needPremultiply =
+                        OGLGraphics2D.enableAlphaComposite(
+                                (AlphaComposite) comp,
+                                srcCM.isAlphaPremultiplied(),
+                                srcCM.hasAlpha()
+                        );
+                needRestoreComposite = true;
+            }
+        } else {
+            // XXX - todo - custom composite
+        }
+
+        boolean oglSrc = false; //srcSurf instanceof OGLSurface;
+
+        if (xform == null && !oglSrc) {
+            // glCopyPixels works very slow on some NV GPU's.
+            /*
+            boolean copied = (srcSurf instanceof OGLSurface) &&
+                oglg.copyArea(
+                        srcX, srcY,
+                        width, height,
+                        dstX, dstY,
+                        ((OGLSurface) srcSurf).oglg
+                );
+
+            if(!copied) {
+            */
+            blitImg2OGL(
+                    srcSurf,
+                    width, height,
+                    dstX, dstY,
+                    needPremultiply
+            );
+            //}
+        } else {
+            OGLTextureParams tp;
+            if (oglSrc) { // We have opengl source with or w/o transform
+                tp = blitOGL2OGLTexCached(
+                        (OGLSurface) srcSurf,
+                        oglDstSurf,
+                        srcX, srcY,
+                        dstX, dstY,
+                        width, height
+                );
+
+                if (tp == null) { // Can't copy texture, use readPixels
+                    oglSrc = false;
+                    tp = blitImg2OGLTexCached(
+                            srcSurf,
+                            width, height,
+                            needPremultiply
+                    );
+                }
+            } else { // Non opengl source
+                tp = blitImg2OGLTexCached(
+                        srcSurf,
+                        width, height,
+                        needPremultiply
+                );
+            }
+
+            double xCoord = (double)width/tp.p2w;
+            double yCoord = (double)height/tp.p2h;
+
+            double vertices[] = new double[8];
+            if (!oglSrc) {
+                vertices[0] = srcX;
+                vertices[1] = srcY;
+                vertices[2] = srcX + width;
+                vertices[3] = srcY;
+                vertices[4] = srcX + width;
+                vertices[5] = srcY + height;
+                vertices[6] = srcX;
+                vertices[7] = srcY + height;
+            } else {
+                vertices[6] = srcX;
+                vertices[7] = srcY;
+                vertices[4] = srcX + width;
+                vertices[5] = srcY;
+                vertices[2] = srcX + width;
+                vertices[3] = srcY + height;
+                vertices[0] = srcX;
+                vertices[1] = srcY + height;
+            }
+
+            if (xform != null) {
+                xform.transform(vertices, 0, vertices, 0, 4);
+            }
+
+            for (int i = 0; i < vertices.length; i++) {
+                vertices[i] += (i%2 == 0) ? dstX : dstY;
+            }
+
+            gl.glEnable(GLDefs.GL_TEXTURE_2D);
+            gl.glBegin(GLDefs.GL_QUADS);
+
+            gl.glTexCoord2d(0.0, 0.0);
+            gl.glVertex2d(vertices[0], vertices[1]);
+            gl.glTexCoord2d(xCoord, 0.0);
+            gl.glVertex2d(vertices[2], vertices[3]);
+            gl.glTexCoord2d(xCoord, yCoord);
+            gl.glVertex2d(vertices[4], vertices[5]);
+            gl.glTexCoord2d(0.0, yCoord);
+            gl.glVertex2d(vertices[6], vertices[7]);
+
+            gl.glEnd();
+            gl.glFlush();
+            gl.glDisable(GLDefs.GL_TEXTURE_2D);
+
+            //tp.deleteTexture();
+        }
+
+        if (needRestoreClip) {
+            oglg.setTransformedClip(oldClip);
+        }
+
+        if (needRestoreComposite) {
+            oglg.checkComposite();
+        }
+    }
+
+    private void blitImg2OGL(
+            Surface srcSurf,
+            int width, int height,
+            int dstX, int dstY,
+            boolean needPremultiply
+    ) {
+        OGLImageParams imageParams = IMAGE_TYPE_MAPPING[srcSurf.getSurfaceType()];
+        boolean requiresConversion = imageParams.requiresConversion;
+        if (requiresConversion || needPremultiply) {
+            imageParams = IMAGE_TYPE_MAPPING[BufferedImage.TYPE_INT_ARGB_PRE];
+        }
+
+        gl.glPixelStorei(GLDefs.GL_UNPACK_ALIGNMENT, imageParams.oglAlignment);
+
+        ColorModel srcCM = srcSurf.getColorModel();
+
+        // Obtain image data in opengl-compatible format and draw the image
+        if (requiresConversion || needPremultiply) {
+            // Set the raster position to the destination point
+            gl.glRasterPos2i(0, 0);
+            gl.glBitmap(0, 0, 0, 0, dstX, -dstY, 0);
+
+            gl.glPixelZoom(1, -1);
+
+            // needPremultiply should be always false for OGLSurface, type cast is safe
+            gl.glDrawPixels(
+                    width, height,
+                    imageParams.oglFormat, imageParams.oglType,
+                    ((ImageSurface) srcSurf).getCachedData(
+                            srcCM.isAlphaPremultiplied() || needPremultiply
+                    )
+            );
+        } else {
+            Object data;
+            if (srcSurf instanceof OGLSurface) {
+                data = ((OGLSurface) srcSurf).getBottomToTopData();
+
+                // Set the raster position to the destination point
+                gl.glRasterPos2i(0, 0);
+                gl.glBitmap(0, 0, 0, 0, dstX, -dstY-height, 0);
+
+                gl.glPixelZoom(1, 1);
+            } else {
+                data = srcSurf.getData();
+
+                // Set the raster position to the destination point
+                gl.glRasterPos2i(0, 0);
+                gl.glBitmap(0, 0, 0, 0, dstX, -dstY, 0);
+
+                gl.glPixelZoom(1, -1);
+            }
+
+            LockedArray ldata = Utils.arraccess.lockArrayShort(data);
+            gl.glDrawPixels(
+                    width, height,
+                    imageParams.oglFormat, imageParams.oglType,
+                    ldata.getAddress()
+            );
+            ldata.release();
+        }
+    }
+
+    /**
+     * Calculates the next power of 2 from the size
+     * @param size - arbitrary positive integer
+     * @return next to the size power of 2
+     */
+    private final static int p2(int size) {
+        size--;
+        size |= size >> 1;
+        size |= size >> 2;
+        size |= size >> 4;
+        size |= size >> 8;
+        size |= size >> 16;
+        return ++size;
+    }
+
+    private final OGLTextureParams blitImg2OGLTex(
+            Surface srcSurf,
+            int width, int height,
+            boolean needPremultiply,
+            OGLTextureParams tp
+    ) {
+        OGLImageParams imageParams = IMAGE_TYPE_MAPPING[srcSurf.getSurfaceType()];
+        boolean requiresConversion = imageParams.requiresConversion;
+        if (requiresConversion || needPremultiply) {
+            imageParams = IMAGE_TYPE_MAPPING[BufferedImage.TYPE_INT_ARGB_PRE];
+        }
+
+        gl.glPixelStorei(GLDefs.GL_UNPACK_ALIGNMENT, imageParams.oglAlignment);
+
+        ColorModel srcCM = srcSurf.getColorModel();
+
+        int p2w = p2(width);
+        int p2h = p2(height);
+
+        if (tp == null) {
+            Int32Pointer texPtr =
+                    NativeBridge.getInstance().createInt32Pointer(1, true);
+
+            gl.glGenTextures(1, texPtr);
+            int texName = texPtr.get(0);
+            gl.glBindTexture(GLDefs.GL_TEXTURE_2D, texName);
+            texPtr.free();
+
+            gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_MAG_FILTER, GLDefs.GL_NEAREST);
+            gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_MIN_FILTER, GLDefs.GL_NEAREST);
+
+            tp = new OGLTextureParams(texName, p2w, p2h, width, height);
+        } else {
+            gl.glBindTexture(GLDefs.GL_TEXTURE_2D, tp.textureName);
+            tp.width = width;
+            tp.height = height;
+            tp.p2w = p2w;
+            tp.p2h = p2h;
+        }
+
+        // XXX - todo - check for texture non p2 extension
+        gl.glTexImage2D(
+                GLDefs.GL_TEXTURE_2D, 0,
+                imageParams.oglIntFormat,
+                p2w, p2h, 0,
+                imageParams.oglFormat, imageParams.oglType,
+                0
+        );
+
+        // Obtain image data in opengl-compatible format and draw the image
+        if (requiresConversion || needPremultiply) {
+            // needPremultiply should be always false for OGLSurface, type cast is safe
+            gl.glTexSubImage2D(
+                    GLDefs.GL_TEXTURE_2D, 0, 0, 0,
+                    //imageParams.oglIntFormat,
+                    width, height, // 0,
+                    imageParams.oglFormat, imageParams.oglType,
+                    ((ImageSurface) srcSurf).getCachedData(
+                            srcCM.isAlphaPremultiplied() || needPremultiply
+                    )
+            );
+        } else {
+            Object data = srcSurf.getData();
+            LockedArray ldata = Utils.arraccess.lockArrayShort(data);
+            gl.glTexSubImage2D(
+                    GLDefs.GL_TEXTURE_2D, 0, 0, 0,
+                    //imageParams.oglIntFormat,
+                    width, height, //0,
+                    imageParams.oglFormat, imageParams.oglType,
+                    ldata.getAddress()
+            );
+
+            ldata.release();
+        }
+
+        return tp;
+    }
+
+    final OGLTextureParams blitImg2OGLTexCached(
+            Surface srcSurf,
+            int width, int height,
+            boolean needPremultiply
+    ) {
+        TextureCache tc = TextureCache.getInstance();
+        OGLTextureParams tp = tc.findTexture(srcSurf);
+
+        if (tp != null) {
+            if (width > tp.width || height > tp.height || !srcSurf.isCaheValid(tp)) {
+                tp = blitImg2OGLTex(
+                        srcSurf,
+                        width, height,
+                        needPremultiply,
+                        tp
+                );
+                srcSurf.addValidCache(tp);
+            } else {
+                gl.glBindTexture(GLDefs.GL_TEXTURE_2D, tp.textureName);
+            }
+        } else {
+            tp = blitImg2OGLTex(
+                    srcSurf,
+                    width, height,
+                    needPremultiply,
+                    null
+            );
+            tc.add(srcSurf, tp);
+            srcSurf.addValidCache(tp);
+            tc.cleanupTextures();
+        }
+
+        gl.glTexEnvf(GLDefs.GL_TEXTURE_ENV, GLDefs.GL_TEXTURE_ENV_MODE, GLDefs.GL_REPLACE);
+
+        return tp;
+    }
+
+    private final OGLTextureParams blitOGL2OGLTexCached(
+            OGLSurface srcSurf,
+            OGLSurface dstSurf,
+            int srcX, int srcY,
+            int dstX, int dstY,
+            int width, int height
+    ) {
+        TextureCache tc = TextureCache.getInstance();
+        OGLTextureParams tp = tc.findTexture(srcSurf);
+
+        if (tp != null) {
+            if (width > tp.width || height > tp.height || !srcSurf.isCaheValid(tp)) {
+                tp = blitOGL2OGLTex(
+                        srcSurf,
+                        dstSurf,
+                        srcX, srcY,
+                        dstX, dstY,
+                        width, height,
+                        tp
+                );
+                srcSurf.addValidCache(tp);
+            } else {
+                gl.glBindTexture(GLDefs.GL_TEXTURE_2D, tp.textureName);
+            }
+        } else {
+            tp = blitOGL2OGLTex(
+                    srcSurf,
+                    dstSurf,
+                    srcX, srcY,
+                    dstX, dstY,
+                    width, height,
+                    null
+            );
+            tc.add(srcSurf, tp);
+            srcSurf.addValidCache(tp);
+            tc.cleanupTextures();
+        }
+
+        gl.glTexEnvf(GLDefs.GL_TEXTURE_ENV, GLDefs.GL_TEXTURE_ENV_MODE, GLDefs.GL_REPLACE);
+
+        return tp;
+    }
+
+    private final OGLTextureParams blitOGL2OGLTex(
+            OGLSurface srcSurf,
+            OGLSurface dstSurf,
+            int srcX, int srcY,
+            int dstX, int dstY,
+            int width, int height,
+            OGLTextureParams tp
+    ) {
+        OGLImageParams imageParams = IMAGE_TYPE_MAPPING[BufferedImage.TYPE_INT_ARGB_PRE];
+        gl.glPixelStorei(GLDefs.GL_UNPACK_ALIGNMENT, imageParams.oglAlignment);
+
+        int p2w = p2(width);
+        int p2h = p2(height);
+
+        if (tp == null) {
+            Int32Pointer texPtr =
+                    NativeBridge.getInstance().createInt32Pointer(1, true);
+
+            gl.glGenTextures(1, texPtr);
+            int texName = texPtr.get(0);
+            gl.glBindTexture(GLDefs.GL_TEXTURE_2D, texName);
+            texPtr.free();
+
+            gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_MAG_FILTER, GLDefs.GL_NEAREST);
+            gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_MIN_FILTER, GLDefs.GL_NEAREST);
+
+            tp = new OGLTextureParams(texName, p2w, p2h, width, height);
+        } else {
+            gl.glBindTexture(GLDefs.GL_TEXTURE_2D, tp.textureName);
+            tp.width = width;
+            tp.height = height;
+            tp.p2w = p2w;
+            tp.p2h = p2h;
+        }
+
+        // XXX - todo - check for texture non p2 extension
+        gl.glTexImage2D(
+                GLDefs.GL_TEXTURE_2D, 0,
+                imageParams.oglIntFormat,
+                p2w, p2h, 0,
+                imageParams.oglFormat, imageParams.oglType,
+                0
+        );
+
+        // Obtain image data in opengl-compatible format and draw the image
+        boolean copied = dstSurf.oglg.copyArea(
+                srcX, srcY,
+                width, height,
+                dstX, dstY,
+                ((OGLSurface) srcSurf).oglg,
+                true
+        );
+
+        return copied ? tp : null;
+    }
+
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLContextManager.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLContextManager.java?view=auto&rev=440748
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLContextManager.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLContextManager.java Wed Sep  6 09:06:15 2006
@@ -0,0 +1,42 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+package org.apache.harmony.awt.gl.opengl;
+
+public interface OGLContextManager {
+    public static class OffscreenBufferObject {
+        public final long id;
+        public final int width;
+        public final int height;
+
+        public OffscreenBufferObject(long id, int width, int height) {
+            this.id = id;
+            this.width = width;
+            this.height = height;
+        }
+    }
+
+    public long getOGLContext(); // Creates OpenGL context based on GraphicsConfiguration
+    public void destroyOGLContext(long oglContext); // Destroys existing OpenGL context
+    public boolean makeCurrent(long oglContext, long drawable); // Makes OpenGL context current
+    public boolean makeContextCurrent(long oglContext, long draw, long read);
+    public void swapBuffers(long drawable);
+    public OffscreenBufferObject createOffscreenBuffer(int w, int h);
+    public void freeOffscreenBuffer(OffscreenBufferObject handle);
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLGraphics2D.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLGraphics2D.java?view=auto&rev=440748
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLGraphics2D.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLGraphics2D.java Wed Sep  6 09:06:15 2006
@@ -0,0 +1,1307 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package org.apache.harmony.awt.gl.opengl;
+
+import org.apache.harmony.awt.gl.CommonGraphics2D;
+import org.apache.harmony.awt.gl.MultiRectArea;
+import org.apache.harmony.awt.gl.Utils;
+import org.apache.harmony.awt.gl.Surface;
+import org.apache.harmony.awt.gl.render.NullBlitter;
+import org.apache.harmony.awt.wtk.NativeWindow;
+import org.apache.harmony.awt.nativebridge.Int32Pointer;
+import org.apache.harmony.awt.nativebridge.NativeBridge;
+import org.apache.harmony.misc.accessors.LockedArray;
+
+import java.awt.*;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.Point2D;
+import java.util.Arrays;
+import java.math.BigInteger;
+
+public final class OGLGraphics2D extends CommonGraphics2D {
+
+    private static final int[] BLEND_RULE_MAPPING_SRC_PREMULT = new int[] {
+        -1, // No rule
+        GLDefs.GL_ZERO, // 1, Clear
+        GLDefs.GL_ONE, // 2, Src
+        GLDefs.GL_ONE, // 3, SrcOver
+        GLDefs.GL_ONE_MINUS_DST_ALPHA, // 4, DstOver
+        GLDefs.GL_DST_ALPHA, // 5, SrcIn
+        GLDefs.GL_ZERO, // 6, DstIn
+        GLDefs.GL_ONE_MINUS_DST_ALPHA, // 7, SrcOut
+        GLDefs.GL_ZERO, // 8, DstOut
+        GLDefs.GL_ZERO, // 9, Dst
+        GLDefs.GL_DST_ALPHA, // 10, SrcAtop
+        GLDefs.GL_ONE_MINUS_DST_ALPHA, // 11, DstAtop
+        GLDefs.GL_ONE_MINUS_DST_ALPHA // 11, Xor
+    };
+
+    private static final int[] BLEND_RULE_MAPPING_DST = new int[] {
+        -1, // No rule
+        GLDefs.GL_ZERO, // 1, Clear
+        GLDefs.GL_ZERO, // 2, Src
+        GLDefs.GL_ONE_MINUS_SRC_ALPHA, // 3, SrcOver
+        GLDefs.GL_ONE, // 4, DstOver
+        GLDefs.GL_ZERO, // 5, SrcIn
+        GLDefs.GL_SRC_ALPHA, // 6, DstIn
+        GLDefs.GL_ZERO, // 7, SrcOut
+        GLDefs.GL_ONE_MINUS_SRC_ALPHA, // 8, DstOut
+        GLDefs.GL_ONE, // 9, Dst
+        GLDefs.GL_ONE_MINUS_SRC_ALPHA, // 10, SrcAtop
+        GLDefs.GL_SRC_ALPHA, // 11, DstAtop
+        GLDefs.GL_ONE_MINUS_SRC_ALPHA // 11, Xor
+    };
+
+    private static final boolean[] HAVE_MAPPING_NO_PREMULT = new boolean[] {
+        false, // No rule
+        true, // 1, Clear
+        true, // 2, Src
+        true, // 3, SrcOver
+        false, // 4, DstOver
+        false, // 5, SrcIn
+        true, // 6, DstIn
+        false, // 7, SrcOut
+        true, // 8, DstOut
+        true, // 9, Dst
+        false, // 10, SrcAtop
+        false, // 11, DstAtop
+        false // 11, Xor
+    };
+
+    private static final int[] BLEND_RULE_MAPPING_SRC_NO_PREMULT = new int[] {
+        -1, // No rule
+        GLDefs.GL_ZERO, // 1, Clear
+        GLDefs.GL_SRC_ALPHA, // 2, Src
+        GLDefs.GL_SRC_ALPHA, // 3, SrcOver
+        -1, // 4, DstOver
+        -1, // 5, SrcIn
+        GLDefs.GL_ZERO, // 6, DstIn
+        -1, // 7, SrcOut
+        GLDefs.GL_ZERO, // 8, DstOut
+        GLDefs.GL_ZERO, // 9, Dst
+        -1, // 10, SrcAtop
+        -1, // 11, DstAtop
+        -1 // 11, Xor
+    };
+
+    private static final int[] BLEND_RULE_MAPPING_DST_NO_ALPHA = new int[] {
+        -1, // No rule
+        GLDefs.GL_ZERO, // 1, Clear
+        GLDefs.GL_ZERO, // 2, Src
+        GLDefs.GL_ZERO, // 3, SrcOver
+        GLDefs.GL_ONE, // 4, DstOver
+        GLDefs.GL_ZERO, // 5, SrcIn
+        GLDefs.GL_ONE, // 6, DstIn
+        GLDefs.GL_ZERO, // 7, SrcOut
+        GLDefs.GL_ZERO, // 8, DstOut
+        GLDefs.GL_ONE, // 9, Dst
+        GLDefs.GL_ZERO, // 10, SrcAtop
+        GLDefs.GL_ONE, // 11, DstAtop
+        GLDefs.GL_ZERO, // 11, Xor
+    };
+
+    private static final GL gl = GL.getInstance();
+
+    private final double[] javaTransformMx = new double[6];
+    private final double[] glTransformMx = new double[16];
+
+    private OGLContextManager ctxmgr;
+    //private long oglContext;
+
+    private NativeWindow nwin;
+    Rectangle winBounds; // Cached native window bounds
+
+    // Can't use transform from CommonGraphics, want to get all mra's untransformed
+    private AffineTransform glTransform = new AffineTransform();
+
+    private byte fgRgba[] = new byte[4];
+    boolean opaqueColor = true;
+    private float acAlpha = 1.0f;
+
+    private boolean oglPaint = true;
+    private boolean texPaint = false;
+    private boolean nativeLines = true;
+    private boolean scalingTransform = false;
+
+    private short stipplePattern;
+    private int stippleFactor;
+
+    /**
+     * gradTexName is a 2 pixel 1d texture object, used to draw gradient.
+     */
+    private int gradTexName = 0;
+    /**
+     * gradObjectPlane is used for 1d texture coordinates generation
+     * when gradient paint is enabled
+     */
+    private double gradObjectPlane[];
+    private boolean isGPCyclic;
+
+
+    public OGLGraphics2D(NativeWindow nwin, int tx, int ty, MultiRectArea clip) {
+        /*
+        if (nwin instanceof OGLVolatileImage.OGLOffscreenWindow) {
+            ctxmgr = (OGLContextManager) getDeviceConfiguration();
+            ctxmgr.makeCurrent(ctxmgr.getOGLContext(), nwin.getId());
+            return;
+        }
+        */
+        this.nwin = nwin;
+
+        ctxmgr = (OGLContextManager) getDeviceConfiguration();
+        //long oglContext = ctxmgr.getOGLContext();
+
+        // Get the viewport (=native window) width and height
+        winBounds = nwin.getBounds();
+
+        if (clip != null) {
+            Rectangle bounds = clip.getBounds();
+            dstSurf = new OGLSurface(bounds.width, bounds.height, this);
+        } else {
+            dstSurf = new OGLSurface(winBounds.width, winBounds.height, this);
+        }
+
+        makeCurrent();
+
+        resetBounds();
+
+        // Apply the translation
+        gl.glLoadIdentity();
+        glTransform = AffineTransform.getTranslateInstance(tx, ty);
+        gl.glTranslated(tx, ty, 0);
+
+        // Super class constructor sets untransformed clip
+        setTransformedClip(clip);
+
+        origPoint = new Point(tx, ty);
+
+        blitter = OGLBlitter.getInstance();
+    }
+
+    public OGLGraphics2D(NativeWindow nwin, int tx, int ty, int width, int height) {
+        this(nwin, tx, ty, new MultiRectArea(new Rectangle(width, height)));
+    }
+
+    public Graphics create() {
+        OGLGraphics2D res = new OGLGraphics2D(
+                nwin,
+                0, 0,
+                dstSurf.getWidth(), dstSurf.getHeight()
+        );
+
+        copyInternalFields(res);
+
+        // Have to copy transform and clip explicitly, since we use opengl transforms
+        res.setTransform(new AffineTransform(glTransform));
+        if (clip == null)
+            res.setTransformedClip(null);
+        else
+            res.setTransformedClip(new MultiRectArea(clip));
+
+        return res;
+    }
+
+    public void finalize() {
+        super.finalize();
+        try {
+            EventQueue.invokeAndWait(
+                    new Runnable() {
+                        public void run () { dispose(); }
+                    }
+            );
+        } catch (Exception e) {
+            e.printStackTrace(); // Something bad happened
+        }
+    }
+
+    public GraphicsConfiguration getDeviceConfiguration() {
+        GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
+        return env.getDefaultScreenDevice().getDefaultConfiguration();
+    }
+
+    public void copyArea(int x, int y, int width, int height, int dx, int dy) {
+        makeCurrent();
+
+        gl.glPixelZoom(1, 1);
+
+        // Raster position could be outside of the viewport, use glBitmap
+        gl.glRasterPos2i(0, 0);
+        gl.glBitmap(0, 0, 0, 0, x + dx, -y-dy-height, 0);
+
+        x += glTransform.getTranslateX() + 0.5;
+        y += glTransform.getTranslateY() + 0.5;
+
+        gl.glCopyPixels(
+                x, winBounds.height-y-height,
+                width, height,
+                GLDefs.GL_COLOR
+        );
+        gl.glFlush();
+        getSurface().updateScene();
+    }
+
+    public void setPaint(Paint paint) {
+        super.setPaint(paint);
+
+        makeCurrent();
+
+        if (paint instanceof Color) {
+            deactivateTexturePaint();
+            deactivateGradientPaint();
+            setColor((Color)paint);
+            oglPaint = true;
+            texPaint = false;
+        } else if (paint instanceof GradientPaint) {
+            deactivateTexturePaint();
+            activateGradientPaint((GradientPaint) paint);
+            oglPaint = true;
+            texPaint = false;
+        } else if (paint instanceof TexturePaint) {
+            deactivateGradientPaint();
+            activateTexturePaint((TexturePaint) paint);
+            oglPaint = true;
+            texPaint = true;
+        } else {
+            deactivateTexturePaint();
+            deactivateGradientPaint();
+            oglPaint = false;
+            texPaint = false;
+        }
+    }
+
+    void resetPaint() {
+        if (gradTexName != 0) {
+            deactivateTexturePaint();
+            reactivateGradientPaint();
+        } else {
+            setPaint(paint);
+        }
+    }
+
+    public void setColor(Color color) {
+        if (color == null)
+            return;
+
+        super.setColor(color);
+
+        makeCurrent();
+
+        // Set gl color
+        int val = color.getRGB();
+        fgRgba[0] = (byte) ((val >> 16) & 0xFF);
+        fgRgba[1] = (byte) ((val >> 8) & 0xFF);
+        fgRgba[2] = (byte) (val & 0xFF);
+        fgRgba[3] = (byte) ((val >> 24) & 0xFF);
+
+        // Need to premultiply alpha
+        if ((fgRgba[3] & 0xFF) != 0xFF || acAlpha != 1.0f) {
+            float alpha = (fgRgba[3] & 0xFF) / 255.0f;
+            fgRgba[0] = (byte) ((fgRgba[0] & 0xFF) * acAlpha * alpha + 0.5);
+            fgRgba[1] = (byte) ((fgRgba[1] & 0xFF) * acAlpha * alpha + 0.5);
+            fgRgba[2] = (byte) ((fgRgba[2] & 0xFF) * acAlpha * alpha + 0.5);
+            // Also use acAlpha
+            fgRgba[3] = (byte) ((fgRgba[3] & 0xFF) * acAlpha + 0.5);
+        }
+
+        LockedArray lColor = Utils.arraccess.lockArrayShort(fgRgba);
+        gl.glColor4ubv(lColor.getAddress());
+        lColor.release();
+
+        // If color becomes translucent, probably need to enable blending
+        if (opaqueColor != ((fgRgba[3] & 0xFF) == 0xFF)) {
+            opaqueColor = (fgRgba[3] & 0xFF) == 0xFF;
+            checkComposite();
+        }
+
+        // And, finally, update paint
+        if (texPaint) {
+            deactivateTexturePaint();
+            texPaint = false;
+        } else if (gradTexName != 0) {
+            deactivateGradientPaint();
+        }
+        paint = color;
+        oglPaint = true;
+    }
+
+    public void dispose() {
+        super.dispose();
+        /*
+        if (oglContext != 0) {
+            ctxmgr.destroyOGLContext(oglContext);
+            oglContext = 0;
+        }*/
+    }
+
+    final void makeCurrent() {
+        long oglContext = ctxmgr.getOGLContext();
+        ctxmgr.makeCurrent(oglContext, nwin.getId());
+        OGLContextValidator.validateContext(this);
+    }
+
+    private int[] createVertexArray(MultiRectArea mra) {
+        int rect[] = mra.rect;
+        int resSize = (rect[0]-1) << 1;
+
+        int[] res = null;
+
+        if (resSize > 0) {
+            //int resSize = nRects*8;
+            int rectOffset = 1;
+            res = new int[resSize];
+            for (int i = 0; i < resSize; i += 8, rectOffset += 4) {
+                // Left, top
+                res[i] = rect[rectOffset];
+                res[i+1] = rect[rectOffset+1];
+                // Right, top
+                res[i+2] = rect[rectOffset+2] + 1;
+                res[i+3] = rect[rectOffset+1];
+                // Right, bottom
+                res[i+4] = rect[rectOffset+2] + 1;
+                res[i+5] = rect[rectOffset+3] + 1;
+                // Left, bottom
+                res[i+6] = rect[rectOffset];
+                res[i+7] = rect[rectOffset+3] + 1;
+            }
+        }
+
+        return res;
+    }
+
+    protected void fillMultiRectAreaColor(MultiRectArea mra) {
+        makeCurrent();
+
+        if (((mra.rect[0]-1)) > 0) { // Have something to draw
+            int vertices[] = createVertexArray(mra);
+            LockedArray lVertices = Utils.arraccess.lockArrayShort(vertices);
+
+            gl.glVertexPointer(2, GLDefs.GL_INT, 0, lVertices.getAddress());
+            gl.glDrawArrays(GLDefs.GL_QUADS, 0, vertices.length/2);
+
+            lVertices.release();
+        }
+
+        gl.glFlush();
+        getSurface().updateScene();
+    }
+
+    public void drawString(String str, int x, int y) {
+        // XXX - todo
+    }
+
+    protected void setTransformedClip(MultiRectArea clip) {
+        super.setTransformedClip(clip);
+        //if (oglContext != 0) {
+        if (ctxmgr != null) {
+            makeCurrent();
+
+            if(clip == null) { // Disable clip
+                gl.glDisable(GLDefs.GL_STENCIL_TEST);
+                gl.glDisable(GLDefs.GL_SCISSOR_TEST);
+
+            } else if(clip.rect[0] < 5) { // Emplty clip, no drwing allowed
+                gl.glDisable(GLDefs.GL_STENCIL_TEST);
+                gl.glEnable(GLDefs.GL_SCISSOR_TEST);
+                gl.glScissor(0, 0, 0, 0);
+
+            } else if (clip.rect[0] == 5) { // Define scissor box - have only one clip rect
+                gl.glDisable(GLDefs.GL_STENCIL_TEST);
+                gl.glEnable(GLDefs.GL_SCISSOR_TEST);
+
+                // Need to transform clip origin, since ogl transform
+                // is not applied by glScissor
+                // Probably should be (int) (glTransform.getTranslateX() + 0.5)
+                // but this gives a 1 pixel error with swing scrolling
+                int tx = (int) (glTransform.getTranslateX());
+                int ty = (int) (glTransform.getTranslateY());
+
+                gl.glScissor(
+                        clip.rect[1] + tx,
+                        winBounds.height - clip.rect[4] - 1 - ty,
+                        clip.rect[3] - clip.rect[1] + 1,
+                        clip.rect[4] - clip.rect[2] + 1
+                );
+            } else { // Several clip rects, use stencil
+
+                gl.glDisable(GLDefs.GL_SCISSOR_TEST);
+                gl.glEnable(GLDefs.GL_STENCIL_TEST);
+
+                gl.glClear(GLDefs.GL_STENCIL_BUFFER_BIT);
+
+                gl.glColorMask(
+                        (byte) GLDefs.GL_FALSE,
+                        (byte) GLDefs.GL_FALSE,
+                        (byte) GLDefs.GL_FALSE,
+                        (byte) GLDefs.GL_FALSE
+                );
+                gl.glStencilFunc(GLDefs.GL_ALWAYS, 0x1, 0x1);
+                gl.glStencilOp(GLDefs.GL_REPLACE, GLDefs.GL_REPLACE, GLDefs.GL_REPLACE);
+
+                // Draw the clip area into the stencil buffer
+                fillMultiRectAreaColor(clip);
+
+                gl.glColorMask(
+                        (byte) GLDefs.GL_TRUE,
+                        (byte) GLDefs.GL_TRUE,
+                        (byte) GLDefs.GL_TRUE,
+                        (byte) GLDefs.GL_TRUE
+                );
+                gl.glStencilFunc(GLDefs.GL_EQUAL, 0x1, 0x1);
+                gl.glStencilOp(GLDefs.GL_KEEP, GLDefs.GL_KEEP, GLDefs.GL_KEEP);
+            }
+        }
+    }
+
+    public void setTransform(AffineTransform transform) {
+        // If transform is scaling drop native lines and use rasterizer
+        if ((transform.getType() & AffineTransform.TYPE_MASK_SCALE) != 0) {
+            scalingTransform = true;
+        } else {
+            scalingTransform = false;
+        }
+
+        //if (oglContext != 0) {
+        if (ctxmgr != null) {
+            double clipTranslationX =
+                    - transform.getTranslateX() + glTransform.getTranslateX();
+            double clipTranslationY =
+                    - transform.getTranslateY() + glTransform.getTranslateY();
+
+            this.glTransform = transform;
+
+            if (clip != null) {
+                clip.translate(
+                        Math.round((float) clipTranslationX),
+                        Math.round((float) clipTranslationY)
+                );
+            }
+
+            makeCurrent();
+            gl.glLoadIdentity();
+
+            switch (transform.getType()) {
+                case AffineTransform.TYPE_TRANSLATION: {
+                    gl.glTranslated(transform.getTranslateX(), transform.getTranslateY(), 0);
+                    break;
+                }
+
+                case AffineTransform.TYPE_GENERAL_SCALE:
+                case AffineTransform.TYPE_UNIFORM_SCALE: {
+                    gl.glScaled(transform.getScaleX(), transform.getScaleY(), 0);
+                    break;
+                }
+
+                case AffineTransform.TYPE_IDENTITY:
+                    break;
+
+                default: {
+                    transform.getMatrix(javaTransformMx);
+                    Arrays.fill(glTransformMx, 0);
+                    glTransformMx[0] = javaTransformMx[0];
+                    glTransformMx[1] = javaTransformMx[1];
+                    glTransformMx[4] = javaTransformMx[2];
+                    glTransformMx[5] = javaTransformMx[3];
+                    glTransformMx[12] = javaTransformMx[4];
+                    glTransformMx[13] = javaTransformMx[5];
+                    glTransformMx[10] = 1;
+                    glTransformMx[15] = 1;
+
+                    LockedArray lMx = Utils.arraccess.lockArrayShort(glTransformMx);
+                    gl.glLoadMatrixd(lMx.getAddress());
+                    lMx.release();
+                }
+            }
+
+            // Fix line rasterization
+            gl.glTranslated(0.375, 0.375, 0);
+
+            // Update paint if it is TexturePaint or GradientPaint
+            if (texPaint || gradTexName != 0) {
+                resetPaint();
+            }
+        }
+    }
+
+    public Shape getClip() {
+        if (clip == null)
+            return null;
+
+        MultiRectArea res = new MultiRectArea(clip);
+        return res;
+    }
+
+    public Rectangle getClipBounds() {
+        if (clip == null)
+            return null;
+
+        Rectangle res = (Rectangle) clip.getBounds().clone();
+        return res;
+    }
+
+    public AffineTransform getTransform() {
+        return (AffineTransform) glTransform.clone();
+    }
+
+    public void rotate(double theta) {
+        glTransform.rotate(theta);
+        setTransform(glTransform);
+    }
+
+    public void rotate(double theta, double x, double y) {
+        glTransform.rotate(theta, x, y);
+        setTransform(glTransform);
+    }
+
+    public void scale(double sx, double sy) {
+        glTransform.scale(sx, sy);
+        setTransform(glTransform);
+    }
+
+    public void shear(double shx, double shy) {
+        glTransform.shear(shx, shy);
+        setTransform(glTransform);
+    }
+
+    public void transform(AffineTransform at) {
+        AffineTransform newTransform = (AffineTransform) glTransform.clone();
+        newTransform.concatenate(at);
+        setTransform(newTransform);
+    }
+
+    public void translate(double tx, double ty) {
+        AffineTransform newTransform = (AffineTransform) glTransform.clone();
+        newTransform.translate(tx, ty);
+        setTransform(newTransform);
+    }
+
+    public void translate(int tx, int ty) {
+        AffineTransform newTransform = (AffineTransform) glTransform.clone();
+        newTransform.translate(tx, ty);
+        setTransform(newTransform);
+    }
+
+    public void clipRect(int x, int y, int width, int height) {
+        MultiRectArea mra = new MultiRectArea(x, y, x+width-1, y+height-1);
+
+        if (clip == null) {
+            setTransformedClip(mra);
+        } else {
+            clip.intersect(mra);
+            setTransformedClip(clip);
+        }
+    }
+
+    public void fillRect(int x, int y, int width, int height) {
+        if (oglPaint) {
+            makeCurrent();
+            gl.glRectd(x, y, x + width, y + height);
+            gl.glFlush();
+        } else {
+            super.fillRect(x, y, width, height);
+        }
+
+        getSurface().updateScene();
+    }
+
+    public void drawLine(int x1, int y1, int x2, int y2) {
+        if (nativeLines && !scalingTransform && oglPaint) {
+            makeCurrent();
+
+            int vertices[] = new int[4];
+            vertices[0] = x1;
+            vertices[1] = y1;
+            vertices[2] = x2;
+            vertices[3] = y2;
+
+            LockedArray lVertices = Utils.arraccess.lockArrayShort(vertices);
+            gl.glVertexPointer(2, GLDefs.GL_INT, 0, lVertices.getAddress());
+            gl.glDrawArrays(GLDefs.GL_LINES, 0, vertices.length/2);
+            lVertices.release();
+
+            gl.glFlush();
+        } else {
+            super.drawLine(x1, y1, x2, y2);
+        }
+
+        getSurface().updateScene();
+    }
+
+    private final void resetClip() {
+        setTransformedClip(clip);
+    }
+
+    private final void resetColor() {
+        setColor(fgColor);
+    }
+
+    private final void resetTransform() {
+        setTransform(glTransform);
+    }
+
+    private final void resetBounds() {
+        // Set viewport and projection
+        // Always set the viewport to the whole window
+        gl.glViewport(0, 0, winBounds.width, winBounds.height);
+
+        gl.glMatrixMode(GLDefs.GL_PROJECTION);
+        gl.glLoadIdentity();
+        gl.gluOrtho2D(0, winBounds.width, winBounds.height, 0);
+
+        gl.glMatrixMode(GLDefs.GL_MODELVIEW);
+    }
+
+    private static class OGLContextValidator {
+        private static ThreadLocal localCurrentGraphics = new ThreadLocal();
+
+        private static final void validateContext(OGLGraphics2D g) {
+            OGLGraphics2D lastGraphics = (OGLGraphics2D) localCurrentGraphics.get();
+
+            if (lastGraphics == null) {
+                // No graphics was used before in the current thread, so
+                // opengl context of this thread should be initialized first
+
+                // Single-buffered
+                gl.glDrawBuffer(GLDefs.GL_FRONT);
+                gl.glReadBuffer(GLDefs.GL_FRONT);
+
+                gl.glEnableClientState(GLDefs.GL_VERTEX_ARRAY);
+                gl.glDisable(GLDefs.GL_DITHER);
+
+                localCurrentGraphics.set(g);
+
+                if (g.blitter instanceof NullBlitter) {
+                    // Called from constructor, skipping validation.
+                    // Everything will be done in the constructor.
+                    return;
+                } else {
+                    // New context in the thread, but old graphics from other thread,
+                    // have to validate all.
+                    g.resetBounds();
+                    g.resetColor();
+                    g.resetTransform();
+                    g.resetClip();
+                    g.checkComposite();
+                    g.resetStroke();
+                    g.resetPaint();
+                    return;
+                }
+            } else if (g == lastGraphics) { // Should have all the attributes in place
+                return;
+            }
+
+            localCurrentGraphics.set(g);
+
+            if (!g.winBounds.equals(lastGraphics.winBounds)) {
+                g.resetBounds();
+            }
+
+            if (!g.fgColor.equals(lastGraphics.fgColor)) {
+                g.resetColor();
+            }
+
+            boolean transformDiffers = !g.glTransform.equals(lastGraphics.glTransform);
+            if (transformDiffers) {
+                g.resetTransform();
+            }
+
+            if (g.clip == null) {
+                if (lastGraphics.clip != null) {
+                    g.resetClip();
+                }
+            } else if (!g.clip.equals(lastGraphics.clip) || transformDiffers) {
+                g.resetClip();
+            }
+
+            if (!g.composite.equals(lastGraphics.composite)) {
+                g.checkComposite();
+            }
+
+            if (!g.stroke.equals(lastGraphics.stroke)) {
+                g.resetStroke();
+            }
+
+            if (!g.paint.equals(lastGraphics.paint)) {
+                g.resetPaint();
+            }
+        }
+    }
+
+    public void setComposite(Composite composite) {
+        super.setComposite(composite);
+
+        makeCurrent();
+        checkComposite();
+    }
+
+    /**
+     * NOTE - caller should call makeCurrent() before calling this method
+     */
+    final void checkComposite() {
+        if (composite instanceof AlphaComposite) {
+            AlphaComposite ac = (AlphaComposite) composite;
+            acAlpha = ac.getAlpha();
+
+            if (
+                    ac.getAlpha() == 1 && opaqueColor &&
+                    (ac.getRule() == AlphaComposite.SRC_OVER ||
+                     ac.getRule() == AlphaComposite.SRC)
+            ) {
+                gl.glDisable(GLDefs.GL_BLEND);
+            } else {
+                enableAlphaComposite(ac, true, true);
+                //gl.glEnable(GLDefs.GL_BLEND);
+            }
+
+            if (ac.getAlpha() != 1) {
+                setColor(bgColor);
+            }
+        } else {
+            acAlpha = 1.0f;
+        }
+    }
+
+    /**
+     * NOTE - caller should call makeCurrent() before calling this method
+     * @param ac
+     * @param srcPremult
+     * @param srcHasAlpha
+     * @return true if caller should not premultiply the source, false otherwise
+     */
+    final static boolean enableAlphaComposite(AlphaComposite ac, boolean srcPremult, boolean srcHasAlpha) {
+        float acAlpha = ac.getAlpha();
+        int acRule = ac.getRule();
+
+        int srcFactor;
+        int dstFactor;
+        int alphaFactor = BLEND_RULE_MAPPING_SRC_PREMULT[acRule];
+
+        boolean needPremultiply = false;
+
+        if (srcHasAlpha) {
+            if (srcPremult || !HAVE_MAPPING_NO_PREMULT[acRule]) {
+                srcFactor = BLEND_RULE_MAPPING_SRC_PREMULT[acRule];
+                if (!srcPremult) { // Caller should premultiply the source
+                    needPremultiply = true;
+                }
+            } else {
+                srcFactor = BLEND_RULE_MAPPING_SRC_NO_PREMULT[acRule];
+            }
+            dstFactor = BLEND_RULE_MAPPING_DST[acRule];
+        } else {
+            srcFactor = BLEND_RULE_MAPPING_SRC_PREMULT[acRule];
+
+            if (srcFactor == GLDefs.GL_ONE && acAlpha == 1) {
+                gl.glDisable(GLDefs.GL_BLEND);
+                return true;
+            }
+
+            dstFactor = BLEND_RULE_MAPPING_DST_NO_ALPHA[acRule];
+        }
+
+        gl.glEnable(GLDefs.GL_BLEND);
+
+        if (srcFactor == alphaFactor) {
+            gl.glBlendFunc(srcFactor, dstFactor);
+        } else {
+            gl.glBlendFuncSeparate(srcFactor, dstFactor, alphaFactor, dstFactor);
+        }
+
+        // Setup alpha scaling for the case when alpha in AlphaComposite != 1
+        gl.glPixelTransferf(GLDefs.GL_ALPHA_SCALE, acAlpha);
+        if (srcPremult || needPremultiply) {
+            gl.glPixelTransferf(GLDefs.GL_RED_SCALE, acAlpha);
+            gl.glPixelTransferf(GLDefs.GL_GREEN_SCALE, acAlpha);
+            gl.glPixelTransferf(GLDefs.GL_BLUE_SCALE, acAlpha);
+        } else {
+            gl.glPixelTransferf(GLDefs.GL_RED_SCALE, 1);
+            gl.glPixelTransferf(GLDefs.GL_GREEN_SCALE, 1);
+            gl.glPixelTransferf(GLDefs.GL_BLUE_SCALE, 1);
+        }
+
+        return needPremultiply;
+    }
+
+    final OGLSurface getSurface() {
+        return (OGLSurface) dstSurf;
+    }
+
+    void readPixels(int x, int y, int w, int h, Object buffer, boolean topToBottom) {
+        // Save current graphics to restore current context after returning pixels
+        OGLGraphics2D currGraphics = (OGLGraphics2D) OGLContextValidator.localCurrentGraphics.get();
+        makeCurrent();
+/*
+        x += glTransform.getTranslateX() + 0.5;
+        y += glTransform.getTranslateY() + 0.5;
+*/
+        LockedArray lBuffer = Utils.arraccess.lockArrayShort(buffer);
+
+        if (topToBottom) {
+            // Need to read scanlines one-by-one to make them go from top to bottom.
+            // OpenGL allows to read from bottom to top only.
+            int sourceRow = winBounds.height-y-1;
+            for (int i=0; i<h; i++, sourceRow--) {
+                gl.glPixelStorei(GLDefs.GL_PACK_SKIP_ROWS, i);
+                gl.glReadPixels(
+                        x, sourceRow,
+                        w, 1,
+                        GLDefs.GL_BGRA, GLDefs.GL_UNSIGNED_INT_8_8_8_8_REV,
+                        lBuffer.getAddress()
+                );
+            }
+        } else {
+            gl.glReadPixels(
+                    x, winBounds.height-y-h,
+                    w, h,
+                    GLDefs.GL_BGRA, GLDefs.GL_UNSIGNED_INT_8_8_8_8_REV,
+                    lBuffer.getAddress()
+            );
+        }
+
+        lBuffer.release();
+
+        gl.glPixelStorei(GLDefs.GL_PACK_SKIP_ROWS, 0);
+
+        if (currGraphics != null && currGraphics!= this) {
+            currGraphics.makeCurrent();
+        }
+    }
+
+    public void setStroke(Stroke stroke) {
+        super.setStroke(stroke);
+        if (stroke instanceof BasicStroke) {
+            BasicStroke bs = (BasicStroke) stroke;
+            if (bs.getLineWidth() <= 1.) {
+                if (bs.getDashArray() != null) {
+                    if (setLineStipplePattern(bs.getDashArray(), bs.getDashPhase())) {
+                        nativeLines = true;
+                        resetStroke();
+                        return;
+                    }
+                } else {
+                    nativeLines = true;
+                    stipplePattern = 0;
+                    resetStroke();
+                    return;
+                }
+            }
+        }
+
+        nativeLines = false;
+        stipplePattern = 0;
+    }
+
+    /**
+     * Calculates opengl line stipple parameters from dashArray and dashPhase taken from
+     * BasicStroke.
+     * @param dashArray - array, taken from BasicStroke
+     * @param dashPhase - phase, taken from BasicStroke
+     * @return fasle if it is impossible to use glLineStipple, true otherwise.
+     */
+    private boolean setLineStipplePattern(float dashArray[], float dashPhase) {
+        // if there's odd number of elements in the dash array, we repeat it twice
+        int longArrLength = dashArray.length % 2 == 0 ? dashArray.length : dashArray.length * 2;
+        long longArray[] = new long[longArrLength];
+        long longPhase = Math.round(dashPhase);
+        BigInteger gcd = BigInteger.valueOf(Math.round(dashArray[0]));
+        int sum = 0;
+        for (int i = 0; i < longArrLength; i++) {
+            longArray[i] = Math.round(dashArray[i % dashArray.length]);
+            gcd = gcd.gcd(BigInteger.valueOf(longArray[i]));
+            sum += longArray[i];
+        }
+
+        if (dashPhase != 0) {
+            gcd = gcd.gcd(BigInteger.valueOf(longPhase));
+            longPhase /= gcd.longValue();
+        }
+
+        sum /= gcd.longValue();
+
+        if (sum > 16)
+            return false;
+
+        int repeatNum;
+
+        switch (sum) {
+            case 1:
+                repeatNum = 16;
+                break;
+            case 2:
+                repeatNum = 8;
+                break;
+            case 4:
+                repeatNum = 4;
+                break;
+            case 8:
+                repeatNum = 2;
+                break;
+            case 16:
+                repeatNum = 1;
+                break;
+            default:
+                return false;
+        }
+
+        int intPattern = 0;
+        stippleFactor = (int) gcd.longValue();
+
+        for (int i=0; i<repeatNum; i++) {
+            for (int j = longArray.length-1; j >= 0; j--) {
+                long currPatternLen = longArray[j]/stippleFactor;
+                intPattern <<= currPatternLen;
+                if ((j & 0x1) == 0) {
+                    intPattern |= (1 << currPatternLen) - 1;
+                }
+            }
+        }
+
+        if (longPhase != 0) { // cyclic shift
+            intPattern = (intPattern >>> longPhase) | (intPattern << (16-longPhase));
+        }
+
+        stipplePattern = (short) (intPattern & 0xFFFF);
+
+        return true;
+    }
+
+    /**
+     * Validates stroke.
+     */
+    void resetStroke() {
+        if (nativeLines) {
+            // Use opengl only for 1-width lines, don't need to set width
+            if (stipplePattern == 0) {
+                gl.glDisable(GLDefs.GL_LINE_STIPPLE);
+            } else {
+                gl.glEnable(GLDefs.GL_LINE_STIPPLE);
+                gl.glLineStipple(stippleFactor, stipplePattern);
+            }
+        } else {
+            gl.glDisable(GLDefs.GL_LINE_STIPPLE);
+        }
+    }
+
+    public void drawPolygon(Polygon polygon) {
+        drawPolygon(polygon.xpoints, polygon.ypoints, polygon.npoints);
+    }
+
+    public void drawPolygon(int[] xpoints, int[] ypoints, int npoints) {
+        drawPoly(xpoints, ypoints, npoints, true);
+    }
+
+    public void drawPolyline(int[] xpoints, int[] ypoints, int npoints) {
+        drawPoly(xpoints, ypoints, npoints, false);
+    }
+
+    private final void drawPoly(int[] xpoints, int[] ypoints, int npoints, boolean closed) {
+        if (nativeLines && !scalingTransform && oglPaint) {
+            makeCurrent();
+
+            int vertices[] = new int[npoints<<1];
+            for (int i = 0; i < npoints; i++) {
+                vertices[i<<1] = xpoints[i];
+                vertices[(i<<1) + 1] = ypoints[i];
+            }
+
+            LockedArray lVertices = Utils.arraccess.lockArrayShort(vertices);
+            gl.glVertexPointer(2, GLDefs.GL_INT, 0, lVertices.getAddress());
+            gl.glDrawArrays(
+                    closed ? GLDefs.GL_LINE_LOOP : GLDefs.GL_LINE_STRIP,
+                    0,
+                    vertices.length / 2
+            );
+            lVertices.release();
+
+            gl.glFlush();
+        } else {
+            if (closed) {
+                super.drawPolygon(xpoints, ypoints, npoints);
+            } else {
+                super.drawPolyline(xpoints, ypoints, npoints);
+            }
+        }
+
+        getSurface().updateScene();
+    }
+
+    public void draw(Shape s) {
+        // To get proper rasterization quality need to
+        // perform scaling before rasterization
+        if (scalingTransform) {
+            s = stroke.createStrokedShape(s);
+            s = glTransform.createTransformedShape(s);
+            gl.glPushMatrix();
+            gl.glLoadIdentity();
+            fillMultiRectArea(jsr.rasterize(s, 0.5));
+            gl.glPopMatrix();
+        } else {
+            super.draw(s);
+        }
+    }
+
+    void activateTexturePaint(TexturePaint p) {
+        Rectangle2D r = p.getAnchorRect();
+        /*
+        if (r.getX() != 0 || r.getY() != 0) {
+            gl.glPixelStoref(GLDefs.GL_UNPACK_SKIP_PIXELS, (float)r.getX());
+            gl.glPixelStoref(GLDefs.GL_UNPACK_SKIP_ROWS, (float)r.getY());
+        }
+        */
+        Surface srcSurf = Surface.getImageSurface(p.getImage());
+
+        int width = (int) r.getWidth();
+        int height = (int) r.getHeight();
+
+        OGLBlitter oglBlitter = (OGLBlitter) blitter;
+
+        OGLBlitter.OGLTextureParams tp = oglBlitter.blitImg2OGLTexCached(
+                srcSurf,
+                srcSurf.getWidth(), srcSurf.getHeight(),
+                true
+        );
+
+        gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_WRAP_S, GLDefs.GL_REPEAT);
+        gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_WRAP_T, GLDefs.GL_REPEAT);
+
+        gl.glTexGeni(GLDefs.GL_S, GLDefs.GL_TEXTURE_GEN_MODE, GLDefs.GL_OBJECT_LINEAR);
+        gl.glTexGeni(GLDefs.GL_T, GLDefs.GL_TEXTURE_GEN_MODE, GLDefs.GL_OBJECT_LINEAR);
+
+        double sObjPlane[] = new double[4];
+        double tObjPlane[] = new double[4];
+
+        // If texture is power of two, take [0;1]x[0;1] square - this is the texture
+        // coordinates range. Then create mapping of anchor rect onto it.
+        // For NPOT texture take [0;size/p2size]x[0;size/p2size] square.
+        double widthFactor = (double) width / tp.width * tp.p2w;
+        double heightFactor = (double) height / tp.height * tp.p2h;
+
+        sObjPlane[0] = 1. / widthFactor;
+        sObjPlane[1] = 0;
+        sObjPlane[2] = 0;
+        sObjPlane[3] = -r.getX() / widthFactor;
+
+        tObjPlane[0] = 0;
+        tObjPlane[1] = 1. / heightFactor;
+        tObjPlane[2] = 0;
+        tObjPlane[3] = -r.getY() / heightFactor;
+
+        LockedArray la = Utils.arraccess.lockArrayShort(sObjPlane);
+        gl.glTexGendv(GLDefs.GL_S, GLDefs.GL_OBJECT_PLANE, la.getAddress());
+        la.release();
+        la = Utils.arraccess.lockArrayShort(tObjPlane);
+        gl.glTexGendv(GLDefs.GL_T, GLDefs.GL_OBJECT_PLANE, la.getAddress());
+        la.release();
+
+        gl.glEnable(GLDefs.GL_TEXTURE_GEN_S);
+        gl.glEnable(GLDefs.GL_TEXTURE_GEN_T);
+
+        gl.glEnable(GLDefs.GL_TEXTURE_2D);
+    }
+    /*
+    static final void reactivateTexturePaint() {
+        gl.glEnable(GLDefs.GL_TEXTURE_GEN_S);
+        gl.glEnable(GLDefs.GL_TEXTURE_GEN_T);
+        gl.glEnable(GLDefs.GL_TEXTURE_2D);
+    }
+    */
+    static final void deactivateTexturePaint() {
+        gl.glDisable(GLDefs.GL_TEXTURE_GEN_S);
+        gl.glDisable(GLDefs.GL_TEXTURE_GEN_T);
+        gl.glDisable(GLDefs.GL_TEXTURE_2D);
+    }
+
+    protected void fillMultiRectAreaPaint(MultiRectArea mra) {
+        if (oglPaint) {
+            fillMultiRectAreaColor(mra);
+        } else {
+            super.fillMultiRectAreaPaint(mra);
+        }
+    }
+
+    private final void activateGradientPaint(GradientPaint gp) {
+        byte twoPixels[] = new byte[8];
+        int val1 = gp.getColor1().getRGB();
+        int val2 = gp.getColor2().getRGB();
+        twoPixels[0] = (byte) ((val1 >> 16) & 0xFF);
+        twoPixels[1] = (byte) ((val1 >> 8) & 0xFF);
+        twoPixels[2] = (byte) (val1 & 0xFF);
+        twoPixels[3] = (byte) ((val1 >> 24) & 0xFF);
+        twoPixels[4] = (byte) ((val2 >> 16) & 0xFF);
+        twoPixels[5] = (byte) ((val2 >> 8) & 0xFF);
+        twoPixels[6] = (byte) (val2 & 0xFF);
+        twoPixels[7] = (byte) ((val2 >> 24) & 0xFF);
+
+        // Get gradient endpoints in the device space
+        Point2D p1 = gp.getPoint1();
+        Point2D p2 = gp.getPoint2();
+        double x1 = p1.getX();
+        double y1 = p1.getY();
+        double x2 = p2.getX();
+        double y2 = p2.getY();
+        /**
+         * Let us denote by a1, a2 and a3 object plane coefficients for texture s coordinate:
+         *      s = a1*x + a2*y + a3
+         * Want to create following mapping for the texture s coordinate:
+         *  x1,y1 -> 0,25
+         *  x2,y2 -> 0,75
+         *  x3,y3 -> 0,25
+         * where (x3-x1,y3-y1) is perpendicular to (x2-x1,y2-y1).
+         * 0,25 and 0,75 are centers of the first and second pixels, where
+         * the color should have the full intensity.
+         * From this have 3 equations for a1, a2 and a3.
+         * They are solved, using cramer's rule in the code below.
+         */
+        double x3 = x1+y2-y1;
+        double y3 = y1+x1-x2;
+        double d1 = (y3 - y1) * 0.5;
+        double d2 = (x1 - x3) * 0.5;
+        double d = -((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
+        double a1 = d1/d;
+        double a2 = d2/d;
+        double a3 = 0.25 - a1*x1 - a2*y1;
+
+        gradObjectPlane = new double[4];
+        gradObjectPlane[0] = a1;
+        gradObjectPlane[1] = a2;
+        gradObjectPlane[2] = 0;
+        gradObjectPlane[3] = a3;
+
+        // Create 1D texture object
+        Int32Pointer texPtr =
+                NativeBridge.getInstance().createInt32Pointer(1, true);
+        gl.glGenTextures(1, texPtr);
+        gradTexName = texPtr.get(0);
+        gl.glBindTexture(GLDefs.GL_TEXTURE_1D, gradTexName);
+        texPtr.free();
+        gl.glTexParameteri(GLDefs.GL_TEXTURE_1D, GLDefs.GL_TEXTURE_MAG_FILTER, GLDefs.GL_LINEAR);
+        gl.glTexParameteri(GLDefs.GL_TEXTURE_1D, GLDefs.GL_TEXTURE_MIN_FILTER, GLDefs.GL_LINEAR);
+        gl.glTexEnvf(GLDefs.GL_TEXTURE_ENV, GLDefs.GL_TEXTURE_ENV_MODE, GLDefs.GL_REPLACE);
+
+        // Setup texture coordinates generation
+        isGPCyclic = gp.isCyclic();
+        gl.glTexParameteri(
+                GLDefs.GL_TEXTURE_1D,
+                GLDefs.GL_TEXTURE_WRAP_S,
+                isGPCyclic ? GLDefs.GL_REPEAT : GLDefs.GL_CLAMP_TO_EDGE
+        );
+        gl.glTexGeni(GLDefs.GL_S, GLDefs.GL_TEXTURE_GEN_MODE, GLDefs.GL_OBJECT_LINEAR);
+        LockedArray la = Utils.arraccess.lockArrayShort(gradObjectPlane);
+        gl.glTexGendv(GLDefs.GL_S, GLDefs.GL_OBJECT_PLANE, la.getAddress());
+        la.release();
+        gl.glEnable(GLDefs.GL_TEXTURE_GEN_S);
+
+        // Load data into texture
+        la = Utils.arraccess.lockArrayShort(twoPixels);
+        gl.glTexImage1D(
+                GLDefs.GL_TEXTURE_1D,
+                0,
+                GLDefs.GL_RGBA,
+                2,
+                0,
+                GLDefs.GL_RGBA,
+                GLDefs.GL_UNSIGNED_BYTE,
+                la.getAddress()
+        );
+        la.release();
+
+        // Enable 1D texture
+        gl.glEnable(GLDefs.GL_TEXTURE_1D);
+    }
+
+    private final void reactivateGradientPaint() {
+        gl.glBindTexture(GLDefs.GL_TEXTURE_1D, gradTexName);
+        LockedArray la = Utils.arraccess.lockArrayShort(gradObjectPlane);
+        gl.glTexGendv(GLDefs.GL_S, GLDefs.GL_OBJECT_PLANE, la.getAddress());
+        la.release();
+        gl.glTexParameteri(
+                GLDefs.GL_TEXTURE_1D,
+                GLDefs.GL_TEXTURE_WRAP_S,
+                isGPCyclic ? GLDefs.GL_REPEAT : GLDefs.GL_CLAMP_TO_EDGE
+        );
+        gl.glEnable(GLDefs.GL_TEXTURE_1D);
+    }
+
+    private final void deactivateGradientPaint() {
+        gl.glDisable(GLDefs.GL_TEXTURE_1D);
+        if (gradTexName != 0) {
+            OGLBlitter.OGLTextureParams.deleteTexture(gradTexName);
+            gradTexName = 0;
+        }
+    }
+
+    /**
+     * This method supposes that context is already current and validated.
+     * It only changes current read drawable to the drawable of other
+     * OGLGraphics2D object. It returnes false if contexts of this OGLGraphics2D
+     * and OGLGraphics2D passed in read parameter differs. To provide normal operation
+     * after using read drawable caller should restore state by calling makeCurrent().
+     * @param read - OGLGraphics2D which provides read drawable
+     * @return true on success
+     */
+    private final boolean setCurrentRead(OGLGraphics2D read) {
+        long oglContext = ctxmgr.getOGLContext();
+        if (read.ctxmgr.getOGLContext() != oglContext)
+            return false;
+
+        ctxmgr.makeContextCurrent(oglContext, nwin.getId(), read.nwin.getId());
+        return true;
+    }
+
+    boolean copyArea(int x, int y, int width, int height, int dx, int dy, OGLGraphics2D read, boolean texture) {
+        if (!setCurrentRead(read))
+            return false;
+
+        gl.glPixelStoref(GLDefs.GL_UNPACK_SKIP_PIXELS, 0);
+        gl.glPixelStoref(GLDefs.GL_UNPACK_SKIP_ROWS, 0);
+
+        gl.glPixelZoom(1, 1);
+
+        // Raster position could be outside of the viewport, use glBitmap
+        gl.glRasterPos2i(0, 0);
+        gl.glBitmap(0, 0, 0, 0, dx, -dy-height, 0);
+
+        x += read.glTransform.getTranslateX() + 0.5;
+        y += read.glTransform.getTranslateY() + 0.5;
+
+        if (!texture) {
+            gl.glCopyPixels(
+                    x, read.winBounds.height-y-height,
+                    width, height,
+                    GLDefs.GL_COLOR
+            );
+            gl.glFlush();
+
+        } else {
+            gl.glCopyTexSubImage2D(
+                    GLDefs.GL_TEXTURE_2D, 0,
+                    0, 0,
+                    x, read.winBounds.height-y-height,
+                    width, height
+            );
+        }
+
+        getSurface().updateScene();
+
+        makeCurrent();
+        return true;
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLSurface.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLSurface.java?view=auto&rev=440748
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLSurface.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLSurface.java Wed Sep  6 09:06:15 2006
@@ -0,0 +1,127 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package org.apache.harmony.awt.gl.opengl;
+
+import org.apache.harmony.awt.gl.Surface;
+import org.apache.harmony.awt.gl.ImageSurface;
+
+import java.awt.image.*;
+import java.awt.color.ColorSpace;
+
+public class OGLSurface extends Surface {
+    private static final ColorModel cm =
+            new DirectColorModel(
+                    ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                    32, 
+                    0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000,
+                    true, DataBuffer.TYPE_INT
+            );
+
+    OGLGraphics2D oglg;
+
+    private ImageSurface imageSurface;
+    boolean sceneUpdated = true;
+    boolean cachedTopToBottom = true;
+    int cachedData[];
+
+    OGLSurface(int width, int height, OGLGraphics2D g2d) {
+        super.width = width;
+        super.height = height;
+        oglg = g2d;
+    }
+
+    public ColorModel getColorModel() {
+        return cm;
+    }
+
+    public WritableRaster getRaster() {
+        WritableRaster res = cm.createCompatibleWritableRaster(width, height);
+        DataBufferInt dbi = (DataBufferInt) res.getDataBuffer();
+        oglg.readPixels(0, 0, width, height, dbi.getData(), true);
+        return res;
+    }
+
+    /**
+     * Clients should use the returned data only for reading 
+     * @return image data
+     */
+    public synchronized Object getData() {
+        if (!sceneUpdated && cachedData != null && cachedTopToBottom) {
+            return cachedData;
+        }
+
+        if (cachedData == null) {
+            cachedData = new int[width*height];
+        }
+
+        oglg.readPixels(0, 0, width, height, cachedData, true);
+        sceneUpdated = false;
+        cachedTopToBottom = true;
+
+        return cachedData;
+    }
+
+    public synchronized Object getBottomToTopData() {
+        if (!sceneUpdated && cachedData != null && !cachedTopToBottom) {
+            return cachedData;
+        }
+
+        if (cachedData == null) {
+            cachedData = new int[width*height];
+        }
+
+        oglg.readPixels(0, 0, width, height, cachedData, false);
+        sceneUpdated = false;
+        cachedTopToBottom = false;
+
+        return cachedData;
+    }
+
+    public int getSurfaceType() {
+        return BufferedImage.TYPE_INT_ARGB_PRE;
+    }
+
+    public long lock() {
+        return 0;
+    }
+
+    public void unlock() {
+    }
+
+    public void dispose() {
+        imageSurface.dispose();
+    }
+
+    public Surface getImageSurface() {
+        if (imageSurface == null) {
+            imageSurface = new ImageSurface(getColorModel(), getRaster());
+        } else {
+            imageSurface.setRaster(getRaster());
+        }
+
+        return imageSurface;
+    }
+
+    final void updateScene() {
+        sceneUpdated = true;
+        clearValidCaches();
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLVolatileImage.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLVolatileImage.java?view=auto&rev=440748
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLVolatileImage.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLVolatileImage.java Wed Sep  6 09:06:15 2006
@@ -0,0 +1,252 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package org.apache.harmony.awt.gl.opengl;
+
+import org.apache.harmony.awt.gl.GLVolatileImage;
+import org.apache.harmony.awt.gl.Surface;
+import org.apache.harmony.awt.gl.MultiRectArea;
+import org.apache.harmony.awt.wtk.NativeWindow;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import java.lang.reflect.InvocationTargetException;
+
+public class OGLVolatileImage extends GLVolatileImage {
+    //private static final GL gl = GL.getInstance();
+    private static final ImageCapabilities ic = new ImageCapabilities(true);
+
+    private int w;
+    private int h;
+    private OGLOffscreenWindow win;
+    private OGLContextManager ctxmgr;
+    private OGLGraphics2D lastGraphics = null;
+
+    private Disposer disposer = new Disposer();
+
+    /**
+     * Helps us use OGL graphics in the uniform way
+     */
+    public class OGLOffscreenWindow implements NativeWindow {
+        private Rectangle bounds;
+        private OGLContextManager.OffscreenBufferObject pbuffer;
+
+        OGLOffscreenWindow(OGLContextManager.OffscreenBufferObject pbuffer, Rectangle bounds) {
+            this.pbuffer = pbuffer;
+            this.bounds = bounds;
+        }
+
+        private OGLContextManager.OffscreenBufferObject getOffscreenBuffer() {
+            return pbuffer;
+        }
+
+        public long getId() {
+            return pbuffer.id;
+        }
+
+        public Rectangle getBounds() {
+            return bounds;
+        }
+
+        // Following methods are placeholders - not used
+        public void setVisible(boolean v) {
+        }
+        public void setBounds(int x, int y, int w, int h, int boundsMask) {
+        }
+        public Insets getInsets() {
+            return null;
+        }
+        public void setEnabled(boolean value) {
+        }
+        public void setFocusable(boolean value) {
+        }
+        public boolean isFocusable() {
+            return false;
+        }
+        public boolean setFocus(boolean focus) {
+            return false;
+        }
+        public void dispose() {
+        }
+        public void placeAfter(NativeWindow w) {
+        }
+        public void toFront() {
+        }
+        public void toBack() {
+        }
+        public void setResizable(boolean value) {
+        }
+        public void setTitle(String title) {
+        }
+        public void grabMouse() {
+        }
+        public void ungrabMouse() {
+        }
+        public void setState(int state) {
+        }
+        public void setIconImage(Image image) {
+        }
+        public void setAlwaysOnTop(boolean value) {
+        }
+        public void setMaximizedBounds(Rectangle bounds) {
+        }
+        public Point getScreenPos() {
+            return null;
+        }
+        public void setPacked(boolean packed) {
+        }
+        public Surface getSurface() {
+            return null;
+        }
+        public MultiRectArea getObscuredRegion(Rectangle part) {
+            return null;
+        }
+
+        public void setIMStyle() {
+        }
+    }
+
+    public OGLVolatileImage(OGLContextManager ctxmgr, int w, int h) {
+        this.ctxmgr = ctxmgr;
+        this.w = w;
+        this.h = h;
+        this.win = new OGLOffscreenWindow(
+                ctxmgr.createOffscreenBuffer(w, h),
+                new Rectangle(0, 0, w, h)
+        );
+    }
+
+
+    public Surface getImageSurface() {
+        return lastGraphics.getSurface();
+    }
+
+    public boolean contentsLost() {
+        return false;
+    }
+
+    public Graphics2D createGraphics() {/*
+        boolean firstTime = false; // First time we need to clear buffer
+        if (lastGraphics == null) {
+            firstTime = true;
+        }*/
+
+        lastGraphics = new OGLGraphics2D(win, 0, 0, w, h);
+        /*
+        if (firstTime) {
+            lastGraphics.makeCurrent();
+            gl.glClear(GLDefs.GL_COLOR_BUFFER_BIT);
+        }
+        */
+        return lastGraphics;
+    }
+
+    public ImageCapabilities getCapabilities() {
+        return ic;
+    }
+
+    public int getHeight() {
+        return h;
+    }
+
+    public BufferedImage getSnapshot() {
+        Surface s = getImageSurface();
+        return new BufferedImage(s.getColorModel(), s.getRaster(), true, null);
+    }
+
+    public int getWidth() {
+        return w;
+    }
+
+    public int validate(GraphicsConfiguration gc) {
+        if (gc.equals(ctxmgr))
+            return IMAGE_OK;
+        else
+            return IMAGE_INCOMPATIBLE;
+    }
+
+    public Object getProperty(String name, ImageObserver observer) {
+        return UndefinedProperty;
+    }
+
+    public int getWidth(ImageObserver observer) {
+        return w;
+    }
+
+    public int getHeight(ImageObserver observer) {
+        return h;
+    }
+
+    protected void finalize() throws Throwable {
+        super.finalize();
+        disposer.dispose();
+    }
+
+    public void flush() {
+        super.flush();
+        disposer.dispose();
+    }
+
+    private void disposeImpl() {
+        if (win != null) {
+            ctxmgr.freeOffscreenBuffer(win.getOffscreenBuffer());
+            win = null;
+        }
+    }
+
+    private final class Disposer {
+        boolean createdInEventDispatchThread;
+        Thread creatorThread = null;
+        boolean objectDisposed = false;
+
+        Disposer() {
+            createdInEventDispatchThread = EventQueue.isDispatchThread();
+            creatorThread = Thread.currentThread();
+        }
+
+        private final void dispose() {
+            if (!objectDisposed) {
+                Thread disposingThread = Thread.currentThread();
+                if (creatorThread == disposingThread) {
+                    disposeImpl();
+                    objectDisposed = true;
+                } else if (createdInEventDispatchThread) {
+                    try {
+                        EventQueue.invokeAndWait(
+                                new Runnable() {
+                                    public void run () {
+                                        disposeImpl();
+                                    }
+                                }
+                        );
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    } catch (InvocationTargetException e) {
+                        e.printStackTrace();
+                    }
+                    objectDisposed = true;
+                }
+            }
+            // Don't set objectDisposed to true if can't dispose from the current thread.
+            // Threre's still a hope that dispose will be invoked from another thread.
+        }
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/TextureCache.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/TextureCache.java?view=auto&rev=440748
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/TextureCache.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/TextureCache.java Wed Sep  6 09:06:15 2006
@@ -0,0 +1,72 @@
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package org.apache.harmony.awt.gl.opengl;
+
+import org.apache.harmony.awt.gl.Surface;
+
+import java.util.HashMap;
+import java.util.WeakHashMap;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+// XXX - todo - this class could be a prototype for the common resource cache.
+// E.g. opengl contexts could be bounded to the thread that created the context and
+// this cache will manage the destruction of the contexts.
+public class TextureCache {
+    private static HashMap ref2texture = new HashMap();
+
+    private static ThreadLocal localInstance = new ThreadLocal() {
+        public Object initialValue() {
+            return new TextureCache();
+        }
+    };
+
+    static TextureCache getInstance() {
+        return (TextureCache) localInstance.get();
+    }
+
+    private ReferenceQueue rq = new ReferenceQueue();
+    private WeakHashMap surface2ref = new WeakHashMap();
+
+    void add(Surface key, OGLBlitter.OGLTextureParams texture) {
+        WeakReference ref =
+                new WeakReference(key, rq);
+
+        surface2ref.put(key, ref);
+        ref2texture.put(ref, texture);
+
+        //System.out.println("Entry added: " + key + ";" + texture);
+    }
+
+    void cleanupTextures() {
+        WeakReference ref;
+
+        while((ref = (WeakReference) rq.poll()) != null) {
+            OGLBlitter.OGLTextureParams tp =
+                    (OGLBlitter.OGLTextureParams) ref2texture.remove(ref);
+            tp.deleteTexture();
+            //System.out.println("Entry cleaned up: " + tp);
+        }
+    }
+
+    OGLBlitter.OGLTextureParams findTexture(Surface key) {
+        OGLBlitter.OGLTextureParams tp =
+         (OGLBlitter.OGLTextureParams) ref2texture.get(surface2ref.get(key));
+        //System.out.println("Entry looked up: " + key + ";" + tp);
+        return tp;
+    }
+
+    void remove(Surface key) {
+        WeakReference ref = (WeakReference) surface2ref.remove(key);
+        if (ref != null) {
+            ref.clear();
+            OGLBlitter.OGLTextureParams tp =
+                    (OGLBlitter.OGLTextureParams) ref2texture.remove(ref);
+            tp.deleteTexture();
+            //System.out.println("Entry removed: " + key + ";" + tp);
+        }
+    }
+}



Mime
View raw message