src/share/native/sun/java2d/opengl/OGLBlitLoops.c

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -32,10 +32,13 @@
 #include "OGLBlitLoops.h"
 #include "OGLRenderQueue.h"
 #include "OGLSurfaceData.h"
 #include "GraphicsPrimitiveMgr.h"
 
+#include <stdlib.h> // malloc
+#include <string.h> // memcpy
+
 extern OGLPixelFormat PixelFormats[];
 
 /**
  * Inner loop used for copying a source OpenGL "Surface" (window, pbuffer,
  * etc.) to a destination OpenGL "Surface".  Note that the same surface can

@@ -748,10 +751,11 @@
         srcInfo.bounds.y2 > srcInfo.bounds.y1)
     {
         dstOps->GetRasInfo(env, dstOps, &dstInfo);
         if (dstInfo.rasBase) {
             void *pDst = dstInfo.rasBase;
+            void* tempRow;
 
             srcx = srcInfo.bounds.x1;
             srcy = srcInfo.bounds.y1;
             dstx = dstInfo.bounds.x1;
             dsty = dstInfo.bounds.y1;

@@ -775,25 +779,44 @@
             J2dTraceLn4(J2D_TRACE_VERBOSE, "  sx=%d sy=%d w=%d h=%d",
                         srcx, srcy, width, height);
             J2dTraceLn2(J2D_TRACE_VERBOSE, "  dx=%d dy=%d",
                         dstx, dsty);
 
-            // this accounts for lower-left origin of the source region
             srcx = srcOps->xOffset + srcx;
-            srcy = srcOps->yOffset + srcOps->height - (srcy + 1);
 
+            // Note that glReadPixels() is extremely slow!
+            // So we try to call it only once and flip the image using memcpy.
+            if (tempRow = malloc(dstInfo.scanStride)) {
+                // fast path
+                jint i;
+                const jint stride = dstInfo.scanStride;
+                srcy = srcOps->yOffset + srcy;
+                j2d_glReadPixels(srcx, srcy, width, height,
+                                 pf.format, pf.type, pDst);
+                for (i = 0; i < height / 2; ++i) {
+                    void * row1 = PtrAddBytes(pDst, (i * stride));
+                    void * row2 = PtrAddBytes(pDst,(height - i - 1) * stride);
+                    memcpy(tempRow, row1, stride);
+                    memcpy(row1, row2, stride);
+                    memcpy(row2, tempRow, stride);
+                }
+                free(tempRow);
+            } else {
+                // slow path
+                // this accounts for lower-left origin of the source region
+                srcy = srcOps->yOffset + srcOps->height - (srcy + 1);
             // we must read one scanline at a time because there is no way
             // to read starting at the top-left corner of the source region
             while (height > 0) {
                 j2d_glPixelStorei(GL_PACK_SKIP_ROWS, dsty);
                 j2d_glReadPixels(srcx, srcy, width, 1,
                                  pf.format, pf.type, pDst);
                 srcy--;
                 dsty++;
                 height--;
             }
-
+            }
 #ifdef MACOSX
             if (srcOps->isOpaque) {
                 j2d_glPixelTransferf(GL_ALPHA_BIAS, 0.0);
             }
 #endif