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,
 813                       OGLContext *oglc, OGLSDOps *dstOps,
 814                       jint x, jint y, jint width, jint height,


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

 784             srcx = srcOps->xOffset + srcx;

 785             
 786             // Note that glReadPixels() is extremely slow!
 787             // So we try to call it only once and flip the image using memcpy.
 788             if (tempRow = malloc(dstInfo.scanStride)) {
 789                 // fast path
 790                 jint i;
 791                 const jint stride = dstInfo.scanStride;
 792                 srcy = srcOps->yOffset + srcy;
 793                 j2d_glReadPixels(srcx, srcy, width, height,
 794                                  pf.format, pf.type, pDst);
 795                 for (i = 0; i < height / 2; ++i) {
 796                     void * row1 = PtrAddBytes(pDst, (i * stride));
 797                     void * row2 = PtrAddBytes(pDst,(height - i - 1) * stride);
 798                     memcpy(tempRow, row1, stride);
 799                     memcpy(row1, row2, stride);
 800                     memcpy(row2, tempRow, stride);
 801                 }
 802                 free(tempRow);
 803             } else {
 804                 // slow path
 805                 // this accounts for lower-left origin of the source region
 806                 srcy = srcOps->yOffset + srcOps->height - (srcy + 1);
 807                 // we must read one scanline at a time because there is no way
 808                 // to read starting at the top-left corner of the source region
 809                 while (height > 0) {
 810                     j2d_glPixelStorei(GL_PACK_SKIP_ROWS, dsty);
 811                     j2d_glReadPixels(srcx, srcy, width, 1,
 812                                      pf.format, pf.type, pDst);
 813                     srcy--;
 814                     dsty++;
 815                     height--;
 816                 }
 817             }
 818 #ifdef MACOSX
 819             if (srcOps->isOpaque) {
 820                 j2d_glPixelTransferf(GL_ALPHA_BIAS, 0.0);
 821             }
 822 #endif
 823 
 824             j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
 825             j2d_glPixelStorei(GL_PACK_SKIP_ROWS, 0);
 826             j2d_glPixelStorei(GL_PACK_ROW_LENGTH, 0);
 827             j2d_glPixelStorei(GL_PACK_ALIGNMENT, 4);
 828         }
 829         SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
 830     }
 831     SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
 832 }
 833 
 834 void
 835 OGLBlitLoops_CopyArea(JNIEnv *env,
 836                       OGLContext *oglc, OGLSDOps *dstOps,
 837                       jint x, jint y, jint width, jint height,