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

Print this page


   1 /*
   2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #ifndef HEADLESS
  27 
  28 #include <jni.h>
  29 #include <jlong.h>
  30 
  31 #include "SurfaceData.h"
  32 #include "OGLBlitLoops.h"
  33 #include "OGLRenderQueue.h"
  34 #include "OGLSurfaceData.h"
  35 #include "GraphicsPrimitiveMgr.h"
  36 



  37 extern OGLPixelFormat PixelFormats[];
  38 
  39 /**
  40  * Inner loop used for copying a source OpenGL "Surface" (window, pbuffer,
  41  * etc.) to a destination OpenGL "Surface".  Note that the same surface can
  42  * be used as both the source and destination, as is the case in a copyArea()
  43  * operation.  This method is invoked from OGLBlitLoops_IsoBlit() as well as
  44  * OGLBlitLoops_CopyArea().
  45  *
  46  * The standard glCopyPixels() mechanism is used to copy the source region
  47  * into the destination region.  If the regions have different dimensions,
  48  * the source will be scaled into the destination as appropriate (only
  49  * nearest neighbor filtering will be applied for simple scale operations).
  50  */
  51 static void
  52 OGLBlitSurfaceToSurface(OGLContext *oglc, OGLSDOps *srcOps, OGLSDOps *dstOps,
  53                         jint sx1, jint sy1, jint sx2, jint sy2,
  54                         jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
  55 {
  56     GLfloat scalex, scaley;


 733     dstInfo.bounds.x2 = dstx + width;
 734     dstInfo.bounds.y2 = dsty + height;
 735 
 736     if (dstOps->Lock(env, dstOps, &dstInfo, SD_LOCK_WRITE) != SD_SUCCESS) {
 737         J2dTraceLn(J2D_TRACE_WARNING,
 738             "OGLBlitLoops_SurfaceToSwBlit: could not acquire dst lock");
 739         return;
 740     }
 741 
 742     SurfaceData_IntersectBoundsXYXY(&srcInfo.bounds,
 743                                     0, 0, srcOps->width, srcOps->height);
 744     SurfaceData_IntersectBlitBounds(&dstInfo.bounds, &srcInfo.bounds,
 745                                     srcx - dstx, srcy - dsty);
 746 
 747     if (srcInfo.bounds.x2 > srcInfo.bounds.x1 &&
 748         srcInfo.bounds.y2 > srcInfo.bounds.y1)
 749     {
 750         dstOps->GetRasInfo(env, dstOps, &dstInfo);
 751         if (dstInfo.rasBase) {
 752             void *pDst = dstInfo.rasBase;


 753 
 754             srcx = srcInfo.bounds.x1;
 755             srcy = srcInfo.bounds.y1;
 756             dstx = dstInfo.bounds.x1;
 757             dsty = dstInfo.bounds.y1;
 758             width = srcInfo.bounds.x2 - srcInfo.bounds.x1;
 759             height = srcInfo.bounds.y2 - srcInfo.bounds.y1;
 760 
 761             j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, dstx);
 762             j2d_glPixelStorei(GL_PACK_ROW_LENGTH,
 763                               dstInfo.scanStride / dstInfo.pixelStride);
 764             j2d_glPixelStorei(GL_PACK_ALIGNMENT, pf.alignment);
 765 #ifdef MACOSX
 766             if (srcOps->isOpaque) {
 767                 // For some reason Apple's OpenGL implementation will
 768                 // read back zero values from the alpha channel of an
 769                 // opaque surface when using glReadPixels(), so here we
 770                 // force the resulting pixels to be fully opaque.
 771                 j2d_glPixelTransferf(GL_ALPHA_BIAS, 1.0);
 772             }
 773 #endif
 774 
 775             J2dTraceLn4(J2D_TRACE_VERBOSE, "  sx=%d sy=%d w=%d h=%d",
 776                         srcx, srcy, width, height);
 777             J2dTraceLn2(J2D_TRACE_VERBOSE, "  dx=%d dy=%d",
 778                         dstx, dsty);
 779 
 780             // this accounts for lower-left origin of the source region
 781             srcx = srcOps->xOffset + srcx;
 782             srcy = srcOps->yOffset + srcOps->height - (srcy + 1);
 783 




















 784             // we must read one scanline at a time because there is no way
 785             // to read starting at the top-left corner of the source region
 786             while (height > 0) {
 787                 j2d_glPixelStorei(GL_PACK_SKIP_ROWS, dsty);
 788                 j2d_glReadPixels(srcx, srcy, width, 1,
 789                                  pf.format, pf.type, pDst);
 790                 srcy--;
 791                 dsty++;
 792                 height--;

 793             }
 794 
 795 #ifdef MACOSX
 796             if (srcOps->isOpaque) {
 797                 j2d_glPixelTransferf(GL_ALPHA_BIAS, 0.0);
 798             }
 799 #endif
 800 
 801             j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
 802             j2d_glPixelStorei(GL_PACK_SKIP_ROWS, 0);
 803             j2d_glPixelStorei(GL_PACK_ROW_LENGTH, 0);
 804             j2d_glPixelStorei(GL_PACK_ALIGNMENT, 4);
 805         }
 806         SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
 807     }
 808     SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
 809 }
 810 
 811 void
 812 OGLBlitLoops_CopyArea(JNIEnv *env,


   1 /*
   2  * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #ifndef HEADLESS
  27 
  28 #include <jni.h>
  29 #include <jlong.h>
  30 
  31 #include "SurfaceData.h"
  32 #include "OGLBlitLoops.h"
  33 #include "OGLRenderQueue.h"
  34 #include "OGLSurfaceData.h"
  35 #include "GraphicsPrimitiveMgr.h"
  36 
  37 #include <stdlib.h> // malloc
  38 #include <string.h> // memcpy
  39 
  40 extern OGLPixelFormat PixelFormats[];
  41 
  42 /**
  43  * Inner loop used for copying a source OpenGL "Surface" (window, pbuffer,
  44  * etc.) to a destination OpenGL "Surface".  Note that the same surface can
  45  * be used as both the source and destination, as is the case in a copyArea()
  46  * operation.  This method is invoked from OGLBlitLoops_IsoBlit() as well as
  47  * OGLBlitLoops_CopyArea().
  48  *
  49  * The standard glCopyPixels() mechanism is used to copy the source region
  50  * into the destination region.  If the regions have different dimensions,
  51  * the source will be scaled into the destination as appropriate (only
  52  * nearest neighbor filtering will be applied for simple scale operations).
  53  */
  54 static void
  55 OGLBlitSurfaceToSurface(OGLContext *oglc, OGLSDOps *srcOps, OGLSDOps *dstOps,
  56                         jint sx1, jint sy1, jint sx2, jint sy2,
  57                         jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
  58 {
  59     GLfloat scalex, scaley;


 736     dstInfo.bounds.x2 = dstx + width;
 737     dstInfo.bounds.y2 = dsty + height;
 738 
 739     if (dstOps->Lock(env, dstOps, &dstInfo, SD_LOCK_WRITE) != SD_SUCCESS) {
 740         J2dTraceLn(J2D_TRACE_WARNING,
 741             "OGLBlitLoops_SurfaceToSwBlit: could not acquire dst lock");
 742         return;
 743     }
 744 
 745     SurfaceData_IntersectBoundsXYXY(&srcInfo.bounds,
 746                                     0, 0, srcOps->width, srcOps->height);
 747     SurfaceData_IntersectBlitBounds(&dstInfo.bounds, &srcInfo.bounds,
 748                                     srcx - dstx, srcy - dsty);
 749 
 750     if (srcInfo.bounds.x2 > srcInfo.bounds.x1 &&
 751         srcInfo.bounds.y2 > srcInfo.bounds.y1)
 752     {
 753         dstOps->GetRasInfo(env, dstOps, &dstInfo);
 754         if (dstInfo.rasBase) {
 755             void *pDst = dstInfo.rasBase;
 756             void* tempRow;
 757             jint clippedStride;
 758 
 759             srcx = srcInfo.bounds.x1;
 760             srcy = srcInfo.bounds.y1;
 761             dstx = dstInfo.bounds.x1;
 762             dsty = dstInfo.bounds.y1;
 763             width = srcInfo.bounds.x2 - srcInfo.bounds.x1;
 764             height = srcInfo.bounds.y2 - srcInfo.bounds.y1;
 765 
 766             pDst = PtrAddBytes(pDst, dstx * dstInfo.pixelStride);   
 767             j2d_glPixelStorei(GL_PACK_ROW_LENGTH,
 768                               dstInfo.scanStride / dstInfo.pixelStride);
 769             j2d_glPixelStorei(GL_PACK_ALIGNMENT, pf.alignment);
 770 #ifdef MACOSX
 771             if (srcOps->isOpaque) {
 772                 // For some reason Apple's OpenGL implementation will
 773                 // read back zero values from the alpha channel of an
 774                 // opaque surface when using glReadPixels(), so here we
 775                 // force the resulting pixels to be fully opaque.
 776                 j2d_glPixelTransferf(GL_ALPHA_BIAS, 1.0);
 777             }
 778 #endif
 779 
 780             J2dTraceLn4(J2D_TRACE_VERBOSE, "  sx=%d sy=%d w=%d h=%d",
 781                         srcx, srcy, width, height);
 782             J2dTraceLn2(J2D_TRACE_VERBOSE, "  dx=%d dy=%d",
 783                         dstx, dsty);
 784 
 785             // this accounts for lower-left origin of the source region
 786             srcx = srcOps->xOffset + srcx;
 787             srcy = srcOps->yOffset + srcOps->height - (srcy + 1);
 788             
 789             // Note that glReadPixels() is extremely slow!
 790             // So we try to call it only once and flip the image using memcpy.
 791             clippedStride = dstInfo.pixelStride * width;
 792             if (tempRow = malloc(clippedStride)) {
 793                 // fast path
 794                 jint i;
 795                 srcy = srcy - height + 1;
 796                 pDst = PtrAddBytes(pDst, dsty * dstInfo.scanStride);
 797                 j2d_glReadPixels(srcx, srcy, width, height,
 798                                  pf.format, pf.type, pDst);
 799                 for (i = 0; i < height / 2; ++i) {
 800                     void * row1 = PtrAddBytes(pDst, (i * dstInfo.scanStride));
 801                     void * row2 = PtrAddBytes(pDst,(height - i - 1) * dstInfo.scanStride);
 802                     memcpy(tempRow, row1, clippedStride);
 803                     memcpy(row1, row2, clippedStride);
 804                     memcpy(row2, tempRow, clippedStride);
 805                 }
 806                 free(tempRow);
 807             } else {
 808                 // slow path
 809                 // we must read one scanline at a time because there is no way
 810                 // to read starting at the top-left corner of the source region
 811                 while (height > 0) {
 812                     j2d_glPixelStorei(GL_PACK_SKIP_ROWS, dsty);
 813                     j2d_glReadPixels(srcx, srcy, width, 1,
 814                                      pf.format, pf.type, pDst);
 815                     srcy--;
 816                     dsty++;
 817                     height--;
 818                 }
 819             }
 820 
 821 #ifdef MACOSX
 822             if (srcOps->isOpaque) {
 823                 j2d_glPixelTransferf(GL_ALPHA_BIAS, 0.0);
 824             }
 825 #endif
 826 
 827             j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
 828             j2d_glPixelStorei(GL_PACK_SKIP_ROWS, 0);
 829             j2d_glPixelStorei(GL_PACK_ROW_LENGTH, 0);
 830             j2d_glPixelStorei(GL_PACK_ALIGNMENT, 4);
 831         }
 832         SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
 833     }
 834     SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
 835 }
 836 
 837 void
 838 OGLBlitLoops_CopyArea(JNIEnv *env,