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