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,
|