6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
authortdv
Thu, 28 Aug 2008 11:27:14 -0700
changeset 1723 4a616c1eac0b
parent 1722 b676952a5943
child 1724 a22a286aa16f
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop Reviewed-by: campbell, flar
jdk/src/share/classes/sun/java2d/opengl/OGLBlitLoops.java
jdk/src/share/classes/sun/java2d/opengl/OGLSurfaceData.java
jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/ImageTests.java
jdk/src/share/native/sun/java2d/opengl/OGLBlitLoops.c
jdk/src/share/native/sun/java2d/opengl/OGLSurfaceData.c
jdk/src/windows/classes/sun/java2d/d3d/D3DBlitLoops.java
jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java
jdk/src/windows/native/sun/java2d/d3d/D3DBlitLoops.cpp
jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.h
--- a/jdk/src/share/classes/sun/java2d/opengl/OGLBlitLoops.java	Tue Aug 19 16:04:06 2008 -0700
+++ b/jdk/src/share/classes/sun/java2d/opengl/OGLBlitLoops.java	Thu Aug 28 11:27:14 2008 -0700
@@ -25,17 +25,13 @@
 
 package sun.java2d.opengl;
 
-import java.awt.AlphaComposite;
-import java.awt.Color;
 import java.awt.Composite;
 import java.awt.Transparency;
 import java.awt.geom.AffineTransform;
 import java.awt.image.AffineTransformOp;
 import java.awt.image.BufferedImage;
 import java.awt.image.BufferedImageOp;
-import java.awt.image.ColorModel;
 import java.lang.ref.WeakReference;
-import sun.awt.image.BufImgSurfaceData;
 import sun.java2d.SurfaceData;
 import sun.java2d.loops.Blit;
 import sun.java2d.loops.CompositeType;
@@ -84,6 +80,8 @@
                                    OGLSurfaceData.PF_INT_BGR),
             new OGLSwToSurfaceBlit(SurfaceType.IntBgrx,
                                    OGLSurfaceData.PF_INT_BGRX),
+            new OGLSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
+                                   OGLSurfaceData.PF_3BYTE_BGR),
             new OGLSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
                                    OGLSurfaceData.PF_USHORT_565_RGB),
             new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
@@ -106,6 +104,8 @@
                                     OGLSurfaceData.PF_INT_BGR),
             new OGLSwToSurfaceScale(SurfaceType.IntBgrx,
                                     OGLSurfaceData.PF_INT_BGRX),
+            new OGLSwToSurfaceScale(SurfaceType.ThreeByteBgr,
+                                    OGLSurfaceData.PF_3BYTE_BGR),
             new OGLSwToSurfaceScale(SurfaceType.Ushort565Rgb,
                                     OGLSurfaceData.PF_USHORT_565_RGB),
             new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgb,
@@ -127,6 +127,8 @@
                                         OGLSurfaceData.PF_INT_BGR),
             new OGLSwToSurfaceTransform(SurfaceType.IntBgrx,
                                         OGLSurfaceData.PF_INT_BGRX),
+            new OGLSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
+                                        OGLSurfaceData.PF_3BYTE_BGR),
             new OGLSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
                                         OGLSurfaceData.PF_USHORT_565_RGB),
             new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
@@ -155,6 +157,8 @@
                                    OGLSurfaceData.PF_INT_BGR),
             new OGLSwToTextureBlit(SurfaceType.IntBgrx,
                                    OGLSurfaceData.PF_INT_BGRX),
+            new OGLSwToTextureBlit(SurfaceType.ThreeByteBgr,
+                                   OGLSurfaceData.PF_3BYTE_BGR),
             new OGLSwToTextureBlit(SurfaceType.Ushort565Rgb,
                                    OGLSurfaceData.PF_USHORT_565_RGB),
             new OGLSwToTextureBlit(SurfaceType.Ushort555Rgb,
--- a/jdk/src/share/classes/sun/java2d/opengl/OGLSurfaceData.java	Tue Aug 19 16:04:06 2008 -0700
+++ b/jdk/src/share/classes/sun/java2d/opengl/OGLSurfaceData.java	Thu Aug 28 11:27:14 2008 -0700
@@ -120,6 +120,7 @@
     public static final int PF_USHORT_555_RGBX = 8;
     public static final int PF_BYTE_GRAY       = 9;
     public static final int PF_USHORT_GRAY     = 10;
+    public static final int PF_3BYTE_BGR       = 11;
 
     /**
      * SurfaceTypes
--- a/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/ImageTests.java	Tue Aug 19 16:04:06 2008 -0700
+++ b/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/ImageTests.java	Thu Aug 28 11:27:14 2008 -0700
@@ -60,6 +60,9 @@
 import java.awt.image.WritableRaster;
 import java.awt.Transparency;
 import java.awt.geom.AffineTransform;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DataBufferShort;
 import java.util.ArrayList;
 import javax.swing.JComponent;
 
@@ -84,6 +87,7 @@
     static Group.EnableSet bufimgsrcroot;
 
     static Group imgtestroot;
+    static Group imgoptionsroot;
 
     static Group imageOpRoot;
     static Group imageOpOptRoot;
@@ -92,6 +96,7 @@
     static Group bufImgOpTestRoot;
     static Group rasterOpTestRoot;
     static Option opList;
+    static Option doTouchSrc;
 
     static String transNodeNames[] = {
         null, "opaque", "bitmask", "translucent",
@@ -105,9 +110,19 @@
         imageroot = new Group(graphicsroot, "imaging",
                               "Imaging Benchmarks");
         imageroot.setTabbed();
+
         imgsrcroot = new Group.EnableSet(imageroot, "src",
                                          "Image Rendering Sources");
         imgsrcroot.setBordered(true);
+
+        imgoptionsroot = new Group(imgsrcroot, "options",
+                                "Image Source Options");
+        imgoptionsroot.setBordered(true);
+        doTouchSrc =
+            new Option.Toggle(imgoptionsroot, "touchsrc",
+                              "Touch src image before every operation",
+                               Option.Toggle.Off);
+
         imgtestroot = new Group(imageroot, "tests",
                                 "Image Rendering Tests");
         imgtestroot.setBordered(true);
@@ -131,7 +146,11 @@
             new BufImg(BufferedImage.TYPE_INT_RGB);
             new BufImg(BufferedImage.TYPE_INT_ARGB);
             new BufImg(BufferedImage.TYPE_BYTE_GRAY);
+            new BufImg(BufferedImage.TYPE_3BYTE_BGR);
             new BmByteIndexBufImg();
+            new BufImg(BufferedImage.TYPE_INT_RGB, true);
+            new BufImg(BufferedImage.TYPE_INT_ARGB, true);
+            new BufImg(BufferedImage.TYPE_3BYTE_BGR, true);
 
             imageOpRoot = new Group(imageroot, "imageops",
                                     "Image Op Benchmarks");
@@ -193,6 +212,7 @@
     }
 
     public static class Context extends GraphicsTests.Context {
+        boolean touchSrc;
         Image src;
         AffineTransform tx;
     }
@@ -206,6 +226,7 @@
     {
         super(parent, nodeName, description);
         addDependency(imgsrcroot, srcFilter);
+        addDependency(doTouchSrc);
     }
 
     public GraphicsTests.Context createContext() {
@@ -217,6 +238,7 @@
         ImageTests.Context ictx = (ImageTests.Context) ctx;
 
         ictx.src = env.getSrcImage();
+        ictx.touchSrc = env.isEnabled(doTouchSrc);
     }
 
     public abstract static class TriStateImageType extends Group {
@@ -272,13 +294,6 @@
     public static class CompatImg extends TriStateImageType {
         int transparency;
 
-        public static String Descriptions[] = {
-            "Default Compatible Image",
-            "Opaque Compatible Image",
-            "Bitmask Compatible Image",
-            "Translucent Compatible Image",
-        };
-
         public CompatImg(int transparency) {
             super(imgsrcroot,
                   Destinations.CompatImg.ShortNames[transparency],
@@ -296,6 +311,7 @@
 
     public static class BufImg extends TriStateImageType {
         int type;
+        boolean unmanaged;
 
         static int Transparencies[] = {
             Transparency.TRANSLUCENT, // "custom",
@@ -315,15 +331,37 @@
         };
 
         public BufImg(int type) {
+            this(type, false);
+        }
+
+        public BufImg(int type, boolean unmanaged) {
             super(bufimgsrcroot,
+                  (unmanaged ? "unmanaged" : "") +
                   Destinations.BufImg.ShortNames[type],
+                  (unmanaged ? "Unmanaged " : "") +
                   Destinations.BufImg.Descriptions[type],
                   Transparencies[type]);
             this.type = type;
+            this.unmanaged = unmanaged;
         }
 
         public Image makeImage(TestEnvironment env, int w, int h) {
-            return new BufferedImage(w, h, type);
+            BufferedImage img = new BufferedImage(w, h, type);
+            if (unmanaged) {
+                DataBuffer db = img.getRaster().getDataBuffer();
+                if (db instanceof DataBufferInt) {
+                    ((DataBufferInt)db).getData();
+                } else if (db instanceof DataBufferShort) {
+                    ((DataBufferShort)db).getData();
+                } else if (db instanceof DataBufferByte) {
+                    ((DataBufferByte)db).getData();
+                } else {
+                    try {
+                        img.setAccelerationPriority(0.0f);
+                    } catch (Throwable e) {}
+                }
+            }
+            return img;
         }
     }
 
@@ -471,15 +509,33 @@
             g.translate(ictx.orgX, ictx.orgY);
             Image src = ictx.src;
             if (ictx.animate) {
-                do {
-                    g.drawImage(src, x, y, null);
-                    if ((x -= 3) < 0) x += ictx.maxX;
-                    if ((y -= 1) < 0) y += ictx.maxY;
-                } while (--numReps > 0);
+                if (ictx.touchSrc) {
+                    Graphics srcG = src.getGraphics();
+                    do {
+                        srcG.fillRect(0, 0, 1, 1);
+                        g.drawImage(src, x, y, null);
+                        if ((x -= 3) < 0) x += ictx.maxX;
+                        if ((y -= 1) < 0) y += ictx.maxY;
+                    } while (--numReps > 0);
+                } else {
+                    do {
+                        g.drawImage(src, x, y, null);
+                        if ((x -= 3) < 0) x += ictx.maxX;
+                        if ((y -= 1) < 0) y += ictx.maxY;
+                    } while (--numReps > 0);
+                }
             } else {
-                do {
-                    g.drawImage(src, x, y, null);
-                } while (--numReps > 0);
+                if (ictx.touchSrc) {
+                    Graphics srcG = src.getGraphics();
+                    do {
+                        srcG.fillRect(0, 0, 1, 1);
+                        g.drawImage(src, x, y, null);
+                    } while (--numReps > 0);
+                } else {
+                    do {
+                        g.drawImage(src, x, y, null);
+                    } while (--numReps > 0);
+                }
             }
             g.translate(-ictx.orgX, -ictx.orgY);
         }
@@ -505,15 +561,33 @@
             Image src = ictx.src;
             Color bg = Color.orange;
             if (ictx.animate) {
-                do {
-                    g.drawImage(src, x, y, bg, null);
-                    if ((x -= 3) < 0) x += ictx.maxX;
-                    if ((y -= 1) < 0) y += ictx.maxY;
-                } while (--numReps > 0);
+                if (ictx.touchSrc) {
+                    Graphics srcG = src.getGraphics();
+                    do {
+                        srcG.fillRect(0, 0, 1, 1);
+                        g.drawImage(src, x, y, bg, null);
+                        if ((x -= 3) < 0) x += ictx.maxX;
+                        if ((y -= 1) < 0) y += ictx.maxY;
+                    } while (--numReps > 0);
+                } else {
+                    do {
+                        g.drawImage(src, x, y, bg, null);
+                        if ((x -= 3) < 0) x += ictx.maxX;
+                        if ((y -= 1) < 0) y += ictx.maxY;
+                    } while (--numReps > 0);
+                }
             } else {
-                do {
-                    g.drawImage(src, x, y, bg, null);
-                } while (--numReps > 0);
+                if (ictx.touchSrc) {
+                    Graphics srcG = src.getGraphics();
+                    do {
+                        srcG.fillRect(0, 0, 1, 1);
+                        g.drawImage(src, x, y, bg, null);
+                    } while (--numReps > 0);
+                } else {
+                    do {
+                        g.drawImage(src, x, y, bg, null);
+                    } while (--numReps > 0);
+                }
             }
             g.translate(-ictx.orgX, -ictx.orgY);
         }
@@ -524,7 +598,7 @@
 
         public DrawImageScale(String dir, float scale) {
             super(imgtestroot, "drawimagescale"+dir,
-                  "drawImage(img, x, y, w*"+scale+", h*"+scale+", obs);");
+                               "drawImage(img, x, y, w*"+scale+", h*"+scale+", obs);");
             this.scale = scale;
         }
 
@@ -546,15 +620,33 @@
             g.translate(ictx.orgX, ictx.orgY);
             Image src = ictx.src;
             if (ictx.animate) {
-                do {
-                    g.drawImage(src, x, y, w, h, null);
-                    if ((x -= 3) < 0) x += ictx.maxX;
-                    if ((y -= 1) < 0) y += ictx.maxY;
-                } while (--numReps > 0);
+                if (ictx.touchSrc) {
+                    Graphics srcG = src.getGraphics();
+                    do {
+                        srcG.fillRect(0, 0, 1, 1);
+                        g.drawImage(src, x, y, w, h, null);
+                        if ((x -= 3) < 0) x += ictx.maxX;
+                        if ((y -= 1) < 0) y += ictx.maxY;
+                    } while (--numReps > 0);
+                } else {
+                    do {
+                        g.drawImage(src, x, y, w, h, null);
+                        if ((x -= 3) < 0) x += ictx.maxX;
+                        if ((y -= 1) < 0) y += ictx.maxY;
+                    } while (--numReps > 0);
+                }
             } else {
-                do {
-                    g.drawImage(src, x, y, w, h, null);
-                } while (--numReps > 0);
+                Graphics srcG = src.getGraphics();
+                if (ictx.touchSrc) {
+                    do {
+                        srcG.fillRect(0, 0, 1, 1);
+                        g.drawImage(src, x, y, w, h, null);
+                    } while (--numReps > 0);
+                } else {
+                    do {
+                        g.drawImage(src, x, y, w, h, null);
+                    } while (--numReps > 0);
+                }
             }
             g.translate(-ictx.orgX, -ictx.orgY);
         }
@@ -588,17 +680,36 @@
             Image src = ictx.src;
             AffineTransform tx = ictx.tx;
             if (ictx.animate) {
-                do {
-                    tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
-                    g.drawImage(src, tx, null);
-                    if ((x -= 3) < 0) x += ictx.maxX;
-                    if ((y -= 1) < 0) y += ictx.maxY;
-                } while (--numReps > 0);
+                if (ictx.touchSrc) {
+                    Graphics srcG = src.getGraphics();
+                    do {
+                        tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
+                        srcG.fillRect(0, 0, 1, 1);
+                        g.drawImage(src, tx, null);
+                        if ((x -= 3) < 0) x += ictx.maxX;
+                        if ((y -= 1) < 0) y += ictx.maxY;
+                    } while (--numReps > 0);
+                } else {
+                    do {
+                        tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
+                        g.drawImage(src, tx, null);
+                        if ((x -= 3) < 0) x += ictx.maxX;
+                        if ((y -= 1) < 0) y += ictx.maxY;
+                    } while (--numReps > 0);
+                }
             } else {
                 tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
-                do {
-                    g.drawImage(src, tx, null);
-                } while (--numReps > 0);
+                if (ictx.touchSrc) {
+                    Graphics srcG = src.getGraphics();
+                    do {
+                        srcG.fillRect(0, 0, 1, 1);
+                        g.drawImage(src, tx, null);
+                    } while (--numReps > 0);
+                } else {
+                    do {
+                        g.drawImage(src, tx, null);
+                    } while (--numReps > 0);
+                }
             }
             g.translate(-ictx.orgX, -ictx.orgY);
         }
@@ -736,15 +847,33 @@
             Graphics2D g2 = (Graphics2D)ictx.graphics;
             g2.translate(ictx.orgX, ictx.orgY);
             if (ictx.animate) {
-                do {
-                    g2.drawImage(src, op, x, y);
-                    if ((x -= 3) < 0) x += ictx.maxX;
-                    if ((y -= 1) < 0) y += ictx.maxY;
-                } while (--numReps > 0);
+                if (ictx.touchSrc) {
+                    Graphics gSrc = src.getGraphics();
+                    do {
+                        gSrc.fillRect(0, 0, 1, 1);
+                        g2.drawImage(src, op, x, y);
+                        if ((x -= 3) < 0) x += ictx.maxX;
+                        if ((y -= 1) < 0) y += ictx.maxY;
+                    } while (--numReps > 0);
+                } else {
+                    do {
+                        g2.drawImage(src, op, x, y);
+                        if ((x -= 3) < 0) x += ictx.maxX;
+                        if ((y -= 1) < 0) y += ictx.maxY;
+                    } while (--numReps > 0);
+                }
             } else {
-                do {
-                    g2.drawImage(src, op, x, y);
-                } while (--numReps > 0);
+                if (ictx.touchSrc) {
+                    Graphics gSrc = src.getGraphics();
+                    do {
+                        gSrc.fillRect(0, 0, 1, 1);
+                        g2.drawImage(src, op, x, y);
+                    } while (--numReps > 0);
+                } else {
+                    do {
+                        g2.drawImage(src, op, x, y);
+                    } while (--numReps > 0);
+                }
             }
             g2.translate(-ictx.orgX, -ictx.orgY);
         }
@@ -778,9 +907,17 @@
             BufferedImageOp op = ictx.bufImgOp;
             BufferedImage src = ictx.bufSrc;
             BufferedImage dst = ictx.bufDst;
-            do {
-                op.filter(src, dst);
-            } while (--numReps > 0);
+            if (ictx.touchSrc) {
+                Graphics gSrc = src.getGraphics();
+                do {
+                    gSrc.fillRect(0, 0, 1, 1);
+                    op.filter(src, dst);
+                } while (--numReps > 0);
+            } else {
+                do {
+                    op.filter(src, dst);
+                } while (--numReps > 0);
+            }
         }
     }
 
@@ -814,9 +951,17 @@
             RasterOp op = ictx.rasterOp;
             Raster src = ictx.rasSrc;
             WritableRaster dst = ictx.rasDst;
-            do {
-                op.filter(src, dst);
-            } while (--numReps > 0);
+            if (ictx.touchSrc) {
+                Graphics gSrc = ictx.bufSrc.getGraphics();
+                do {
+                    gSrc.fillRect(0, 0, 1, 1);
+                    op.filter(src, dst);
+                } while (--numReps > 0);
+            } else {
+                do {
+                    op.filter(src, dst);
+                } while (--numReps > 0);
+            }
         }
     }
 }
--- a/jdk/src/share/native/sun/java2d/opengl/OGLBlitLoops.c	Tue Aug 19 16:04:06 2008 -0700
+++ b/jdk/src/share/native/sun/java2d/opengl/OGLBlitLoops.c	Thu Aug 28 11:27:14 2008 -0700
@@ -203,7 +203,24 @@
     j2d_glBitmap(0, 0, 0, 0, (GLfloat)dx1, (GLfloat)-dy1, NULL);
 
     j2d_glPixelZoom(scalex, -scaley);
-    j2d_glDrawPixels(sx2-sx1, sy2-sy1, pf->format, pf->type, srcInfo->rasBase);
+
+    // in case pixel stride is not a multiple of scanline stride the copy
+    // has to be done line by line (see 6207877)
+    if (srcInfo->scanStride % srcInfo->pixelStride != 0) {
+        jint width = sx2-sx1;
+        jint height = sy2-sy1;
+        GLvoid *pSrc = srcInfo->rasBase;
+
+        while (height > 0) {
+            j2d_glDrawPixels(width, 1, pf->format, pf->type, pSrc);
+            j2d_glBitmap(0, 0, 0, 0, (GLfloat)0, (GLfloat)-1, NULL);
+            pSrc = PtrAddBytes(pSrc, srcInfo->scanStride);
+            height--;
+        }
+    } else {
+        j2d_glDrawPixels(sx2-sx1, sy2-sy1, pf->format, pf->type, srcInfo->rasBase);
+    }
+
     j2d_glPixelZoom(1.0, 1.0);
 
     if (oglc->extraAlpha != 1.0f) {
@@ -250,6 +267,7 @@
     jint sx, sy, sw, sh;
     GLint glhint = (hint == OGLSD_XFORM_BILINEAR) ? GL_LINEAR : GL_NEAREST;
     jboolean adjustAlpha = (pf != NULL && !pf->hasAlpha);
+    jboolean slowPath;
 
     if (oglc->blitTextureID == 0) {
         if (!OGLContext_InitBlitTileTexture(oglc)) {
@@ -279,6 +297,10 @@
         j2d_glPixelTransferf(GL_ALPHA_BIAS, 1.0f);
     }
 
+    // in case pixel stride is not a multiple of scanline stride the copy
+    // has to be done line by line (see 6207877)
+    slowPath = srcInfo->scanStride % srcInfo->pixelStride != 0;
+
     for (sy = sy1, dy = dy1; sy < sy2; sy += th, dy += cdh) {
         sh = ((sy + th) > sy2) ? (sy2 - sy) : th;
         dh = ((dy + cdh) > dy2) ? (dy2 - dy) : cdh;
@@ -291,13 +313,29 @@
             ty2 = ((GLdouble)sh) / th;
 
             if (swsurface) {
-                j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
-                j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
+                if (slowPath) {
+                    jint tmph = sh;
+                    GLvoid *pSrc = PtrCoord(srcInfo->rasBase,
+                                            sx, srcInfo->pixelStride,
+                                            sy, srcInfo->scanStride);
 
-                j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
-                                    0, 0, sw, sh,
-                                    pf->format, pf->type,
-                                    srcInfo->rasBase);
+                    while (tmph > 0) {
+                        j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
+                                            0, sh - tmph, sw, 1,
+                                            pf->format, pf->type,
+                                            pSrc);
+                        pSrc = PtrAddBytes(pSrc, srcInfo->scanStride);
+                        tmph--;
+                    }
+                } else {
+                    j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
+                    j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
+
+                    j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
+                                        0, 0, sw, sh,
+                                        pf->format, pf->type,
+                                        srcInfo->rasBase);
+                }
 
                 // the texture image is "right side up", so we align the
                 // upper-left texture corner with the upper-left quad corner
@@ -356,9 +394,25 @@
                    jint dx1, jint dy1, jint dx2, jint dy2)
 {
     j2d_glBindTexture(dstOps->textureTarget, dstOps->textureID);
-    j2d_glTexSubImage2D(dstOps->textureTarget, 0,
-                        dx1, dy1, dx2-dx1, dy2-dy1,
-                        pf->format, pf->type, srcInfo->rasBase);
+    // in case pixel stride is not a multiple of scanline stride the copy
+    // has to be done line by line (see 6207877)
+    if (srcInfo->scanStride % srcInfo->pixelStride != 0) {
+        jint width = dx2 - dx1;
+        jint height = dy2 - dy1;
+        GLvoid *pSrc = srcInfo->rasBase;
+
+        while (height > 0) {
+            j2d_glTexSubImage2D(dstOps->textureTarget, 0,
+                                dx1, dy2 - height, width, 1,
+                                pf->format, pf->type, pSrc);
+            pSrc = PtrAddBytes(pSrc, srcInfo->scanStride);
+            height--;
+        }
+    } else {
+        j2d_glTexSubImage2D(dstOps->textureTarget, 0,
+                            dx1, dy1, dx2-dx1, dy2-dy1,
+                            pf->format, pf->type, srcInfo->rasBase);
+    }
 }
 
 /**
--- a/jdk/src/share/native/sun/java2d/opengl/OGLSurfaceData.c	Tue Aug 19 16:04:06 2008 -0700
+++ b/jdk/src/share/native/sun/java2d/opengl/OGLSurfaceData.c	Thu Aug 28 11:27:14 2008 -0700
@@ -73,7 +73,8 @@
       1, 0, 1,                                     }, /* 9 - ByteGray     */
     { GL_LUMINANCE, GL_UNSIGNED_SHORT,
       2, 0, 1,                                     }, /*10 - UshortGray   */
-};
+    { GL_BGR,  GL_UNSIGNED_BYTE,
+      1, 0, 1,                                     }, /*11 - ThreeByteBgr */};
 
 /**
  * Given a starting value and a maximum limit, returns the first power-of-two
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DBlitLoops.java	Tue Aug 19 16:04:06 2008 -0700
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DBlitLoops.java	Thu Aug 28 11:27:14 2008 -0700
@@ -85,6 +85,8 @@
                                    D3DSurfaceData.ST_INT_RGB),
             new D3DSwToSurfaceBlit(SurfaceType.IntBgr,
                                    D3DSurfaceData.ST_INT_BGR),
+            new D3DSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
+                                   D3DSurfaceData.ST_3BYTE_BGR),
             new D3DSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
                                    D3DSurfaceData.ST_USHORT_565_RGB),
             new D3DSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
@@ -106,6 +108,8 @@
                                     D3DSurfaceData.ST_INT_RGB),
             new D3DSwToSurfaceScale(SurfaceType.IntBgr,
                                     D3DSurfaceData.ST_INT_BGR),
+            new D3DSwToSurfaceScale(SurfaceType.ThreeByteBgr,
+                                    D3DSurfaceData.ST_3BYTE_BGR),
             new D3DSwToSurfaceScale(SurfaceType.Ushort565Rgb,
                                     D3DSurfaceData.ST_USHORT_565_RGB),
             new D3DSwToSurfaceScale(SurfaceType.Ushort555Rgb,
@@ -124,6 +128,8 @@
                                         D3DSurfaceData.ST_INT_RGB),
             new D3DSwToSurfaceTransform(SurfaceType.IntBgr,
                                         D3DSurfaceData.ST_INT_BGR),
+            new D3DSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
+                                        D3DSurfaceData.ST_3BYTE_BGR),
             new D3DSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
                                         D3DSurfaceData.ST_USHORT_565_RGB),
             new D3DSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
@@ -147,6 +153,8 @@
                                    D3DSurfaceData.ST_INT_ARGB),
             new D3DSwToTextureBlit(SurfaceType.IntBgr,
                                    D3DSurfaceData.ST_INT_BGR),
+            new D3DSwToTextureBlit(SurfaceType.ThreeByteBgr,
+                                   D3DSurfaceData.ST_3BYTE_BGR),
             new D3DSwToTextureBlit(SurfaceType.Ushort565Rgb,
                                    D3DSurfaceData.ST_USHORT_565_RGB),
             new D3DSwToTextureBlit(SurfaceType.Ushort555Rgb,
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java	Tue Aug 19 16:04:06 2008 -0700
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java	Thu Aug 28 11:27:14 2008 -0700
@@ -135,6 +135,7 @@
     public static final int ST_USHORT_555_RGB  = 6;
     public static final int ST_BYTE_INDEXED    = 7;
     public static final int ST_BYTE_INDEXED_BM = 8;
+    public static final int ST_3BYTE_BGR       = 9;
 
     /** Equals to D3DSWAPEFFECT_DISCARD */
     public static final int SWAP_DISCARD       = 1;
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DBlitLoops.cpp	Tue Aug 19 16:04:06 2008 -0700
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DBlitLoops.cpp	Thu Aug 28 11:27:14 2008 -0700
@@ -47,6 +47,7 @@
 extern "C" BlitFunc IntArgbPreToIntArgbConvert;
 extern "C" BlitFunc IntArgbBmToIntArgbConvert;
 extern "C" BlitFunc IntRgbToIntArgbConvert;
+extern "C" BlitFunc ThreeByteBgrToIntArgbConvert;
 extern "C" BlitFunc Ushort565RgbToIntArgbConvert;
 extern "C" BlitFunc Ushort555RgbToIntArgbConvert;
 extern "C" BlitFunc IntBgrToIntArgbConvert;
@@ -268,6 +269,11 @@
                                    srcWidth, srcHeight,
                                    pSrcInfo, &dstInfo, NULL, NULL);
             break;
+        case ST_3BYTE_BGR:
+            ThreeByteBgrToIntArgbConvert(pSrcBase, pDstBase,
+                                         srcWidth, srcHeight,
+                                         pSrcInfo, &dstInfo, NULL, NULL);
+            break;
         case ST_USHORT_555_RGB:
             Ushort555RgbToIntArgbConvert(pSrcBase, pDstBase,
                                          srcWidth, srcHeight,
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.h	Tue Aug 19 16:04:06 2008 -0700
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.h	Thu Aug 28 11:27:14 2008 -0700
@@ -68,6 +68,7 @@
 #define ST_USHORT_555_RGB  sun_java2d_d3d_D3DSurfaceData_ST_USHORT_555_RGB
 #define ST_BYTE_INDEXED    sun_java2d_d3d_D3DSurfaceData_ST_BYTE_INDEXED
 #define ST_BYTE_INDEXED_BM sun_java2d_d3d_D3DSurfaceData_ST_BYTE_INDEXED_BM
+#define ST_3BYTE_BGR       sun_java2d_d3d_D3DSurfaceData_ST_3BYTE_BGR
 
 /**
  * These are defined to be the same as ExtendedBufferCapabilities.VSyncType