jdk/src/solaris/native/sun/java2d/x11/X11PMBlitLoops.c
changeset 2 90ce3da70b43
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11PMBlitLoops.c	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2000-2007 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#include <stdlib.h>
+#include <jni.h>
+#include <jlong.h>
+#include "X11SurfaceData.h"
+#include "Region.h"
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_x11_X11PMBlitLoops_nativeBlit
+    (JNIEnv *env, jobject joSelf,
+     jlong srcData, jlong dstData,
+     jlong gc, jobject clip,
+     jint srcx, jint srcy,
+     jint dstx, jint dsty,
+     jint width, jint height)
+{
+#ifndef HEADLESS
+    X11SDOps *srcXsdo, *dstXsdo;
+    SurfaceDataBounds span, srcBounds;
+    RegionData clipInfo;
+    GC xgc;
+
+    if (width <= 0 || height <= 0) {
+        return;
+    }
+
+    srcXsdo = (X11SDOps *)jlong_to_ptr(srcData);
+    if (srcXsdo == NULL) {
+        return;
+    }
+    dstXsdo = (X11SDOps *)jlong_to_ptr(dstData);
+    if (dstXsdo == NULL) {
+        return;
+    }
+    if (Region_GetInfo(env, clip, &clipInfo)) {
+        return;
+    }
+
+    xgc = (GC)gc;
+    if (xgc == NULL) {
+        return;
+    }
+
+#ifdef MITSHM
+    if (srcXsdo->isPixmap) {
+        X11SD_UnPuntPixmap(srcXsdo);
+    }
+#endif /* MITSHM */
+
+    /* clip the source rect to the source pixmap's dimensions */
+    srcBounds.x1 = srcx;
+    srcBounds.y1 = srcy;
+    srcBounds.x2 = srcx + width;
+    srcBounds.y2 = srcy + height;
+    SurfaceData_IntersectBoundsXYXY(&srcBounds,
+                                    0, 0, srcXsdo->pmWidth, srcXsdo->pmHeight);
+    span.x1 = dstx;
+    span.y1 = dsty;
+    span.x2 = dstx + width;
+    span.y2 = dsty + height;
+
+    /* intersect the source and dest rects */
+    SurfaceData_IntersectBlitBounds(&srcBounds, &span,
+                                    dstx - srcx, dsty - srcy);
+    srcx = srcBounds.x1;
+    srcy = srcBounds.y1;
+    dstx = span.x1;
+    dsty = span.y1;
+
+    if (srcXsdo->bitmask != 0) {
+        XSetClipOrigin(awt_display, xgc, dstx - srcx, dsty - srcy);
+        XSetClipMask(awt_display, xgc, srcXsdo->bitmask);
+    }
+
+    Region_IntersectBounds(&clipInfo, &span);
+    if (!Region_IsEmpty(&clipInfo)) {
+        Region_StartIteration(env, &clipInfo);
+        srcx -= dstx;
+        srcy -= dsty;
+        while (Region_NextIteration(&clipInfo, &span)) {
+            XCopyArea(awt_display, srcXsdo->drawable, dstXsdo->drawable, xgc,
+                      srcx + span.x1, srcy + span.y1,
+                      span.x2 - span.x1, span.y2 - span.y1,
+                      span.x1, span.y1);
+        }
+        Region_EndIteration(env, &clipInfo);
+    }
+
+    if (srcXsdo->bitmask != 0) {
+        XSetClipMask(awt_display, xgc, None);
+    }
+
+#ifdef MITSHM
+    if (srcXsdo->shmPMData.usingShmPixmap) {
+        srcXsdo->shmPMData.xRequestSent = JNI_TRUE;
+    }
+#endif /* MITSHM */
+    X11SD_DirectRenderNotify(env, dstXsdo);
+#endif /* !HEADLESS */
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_x11_X11PMBlitBgLoops_nativeBlitBg
+    (JNIEnv *env, jobject joSelf,
+     jlong srcData, jlong dstData,
+     jlong xgc, jint pixel,
+     jint srcx, jint srcy,
+     jint dstx, jint dsty,
+     jint width, jint height)
+{
+#ifndef HEADLESS
+    X11SDOps *srcXsdo, *dstXsdo;
+    GC dstGC;
+    SurfaceDataBounds dstBounds, srcBounds;
+    Drawable srcDrawable;
+
+    if (width <= 0 || height <= 0) {
+        return;
+    }
+
+    srcXsdo = (X11SDOps *)jlong_to_ptr(srcData);
+    if (srcXsdo == NULL) {
+        return;
+    }
+    dstXsdo = (X11SDOps *)jlong_to_ptr(dstData);
+    if (dstXsdo == NULL) {
+        return;
+    }
+
+    dstGC = (GC)xgc;
+    if (dstGC == NULL) {
+        return;
+    }
+
+#ifdef MITSHM
+    if (srcXsdo->isPixmap) {
+        X11SD_UnPuntPixmap(srcXsdo);
+    }
+#endif /* MITSHM */
+
+    srcDrawable = srcXsdo->GetPixmapWithBg(env, srcXsdo, pixel);
+    if (srcDrawable == 0) {
+        return;
+    }
+
+    /* clip the source rect to the source pixmap's dimensions */
+    srcBounds.x1 = srcx;
+    srcBounds.y1 = srcy;
+    srcBounds.x2 = srcx + width;
+    srcBounds.y2 = srcy + height;
+    SurfaceData_IntersectBoundsXYXY(&srcBounds,
+                                    0, 0, srcXsdo->pmWidth, srcXsdo->pmHeight);
+    dstBounds.x1 = dstx;
+    dstBounds.y1 = dsty;
+    dstBounds.x2 = dstx + width;
+    dstBounds.y2 = dsty + height;
+
+    /* intersect the source and dest rects */
+    SurfaceData_IntersectBlitBounds(&srcBounds, &dstBounds,
+                                    dstx - srcx, dsty - srcy);
+    srcx = srcBounds.x1;
+    srcy = srcBounds.y1;
+    dstx = dstBounds.x1;
+    dsty = dstBounds.y1;
+    width = srcBounds.x2 - srcBounds.x1;
+    height = srcBounds.y2 - srcBounds.y1;
+
+    /* do an unmasked copy as we've already filled transparent
+       pixels of the source image with the desired color */
+    XCopyArea(awt_display, srcDrawable, dstXsdo->drawable, dstGC,
+              srcx, srcy, width, height, dstx, dsty);
+
+    srcXsdo->ReleasePixmapWithBg(env, srcXsdo);
+    X11SD_DirectRenderNotify(env, dstXsdo);
+#endif /* !HEADLESS */
+}
+
+/*
+ * Class:     sun_java2d_x11_X11PMBlitLoops
+ * Method:    updateBitmask
+ * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_java2d_x11_X11PMBlitLoops_updateBitmask
+    (JNIEnv *env, jclass xpmbl, jobject srcsd, jobject dstsd, jboolean isICM)
+{
+#ifndef HEADLESS
+    SurfaceDataOps *srcOps = SurfaceData_GetOps(env, srcsd);
+    X11SDOps *xsdo = (X11SDOps *) SurfaceData_GetOps(env, dstsd);
+    SurfaceDataRasInfo srcInfo;
+
+    int flags;
+    int screen;
+    int width;
+    int height;
+    jint srcScan, dstScan;
+    int rowCount;
+    unsigned char *pDst;
+    XImage *image;
+    GC xgc;
+
+    if (srcOps == NULL || xsdo == NULL) {
+        JNU_ThrowNullPointerException(env, "Null BISD in updateMaskRegion");
+        return;
+    }
+
+    AWT_LOCK();
+
+    screen = xsdo->configData->awt_visInfo.screen;
+    width = xsdo->pmWidth;
+    height = xsdo->pmHeight;
+
+    if (xsdo->bitmask == 0) {
+        /* create the bitmask if it is not yet created */
+        xsdo->bitmask = XCreatePixmap(awt_display,
+                                      RootWindow(awt_display, screen),
+                                      width, height, 1);
+        if (xsdo->bitmask == 0) {
+            AWT_UNLOCK();
+            JNU_ThrowOutOfMemoryError(env,
+                                      "Cannot create bitmask for "
+                                      "offscreen surface");
+            return;
+        }
+    }
+
+    /* Create a bitmask image and then blit it to the pixmap. */
+    image = XCreateImage(awt_display, DefaultVisual(awt_display, screen),
+                         1, XYBitmap, 0, NULL, width, height, 32, 0);
+    if (image == NULL) {
+        AWT_UNLOCK();
+        JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask");
+        return;
+    }
+    dstScan = image->bytes_per_line;
+    image->data = malloc(dstScan * height);
+    if (image->data == NULL) {
+        XFree(image);
+        AWT_UNLOCK();
+        JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask");
+        return;
+    }
+    pDst = (unsigned char *)image->data;
+
+    srcInfo.bounds.x1 = 0;
+    srcInfo.bounds.y1 = 0;
+    srcInfo.bounds.x2 = width;
+    srcInfo.bounds.y2 = height;
+
+    flags = (isICM ? (SD_LOCK_LUT | SD_LOCK_READ) : SD_LOCK_READ);
+    if (srcOps->Lock(env, srcOps, &srcInfo, flags) != SD_SUCCESS) {
+        XDestroyImage(image);
+        AWT_UNLOCK();
+        return;
+    }
+    srcOps->GetRasInfo(env, srcOps, &srcInfo);
+
+    rowCount = height;
+    if (isICM) {
+        unsigned char *pSrc;
+        jint *srcLut;
+
+        srcScan = srcInfo.scanStride;
+        srcLut = srcInfo.lutBase;
+        pSrc = (unsigned char *)srcInfo.rasBase;
+
+        if (image->bitmap_bit_order == MSBFirst) {
+            do {
+                int x = 0, bx = 0;
+                unsigned int pix = 0;
+                unsigned int bit = 0x80;
+                unsigned char *srcPixel = pSrc;
+                do {
+                    if (bit == 0) {
+                        pDst[bx++] = (unsigned char)pix;
+                        pix = 0;
+                        bit = 0x80;
+                    }
+                    pix |= bit & (srcLut[*srcPixel++] >> 31);
+                    bit >>= 1;
+                } while (++x < width);
+                pDst[bx] = (unsigned char)pix;
+                pDst += dstScan;
+                pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan);
+            } while (--rowCount > 0);
+        } else {
+            do {
+                int x = 0, bx = 0;
+                unsigned int pix = 0;
+                unsigned int bit = 1;
+                unsigned char *srcPixel = pSrc;
+                do {
+                    if ((bit >> 8) != 0) {
+                        pDst[bx++] = (unsigned char) pix;
+                        pix = 0;
+                        bit = 1;
+                    }
+                    pix |= bit & (srcLut[*srcPixel++] >> 31);
+                    bit <<= 1;
+                } while (++x < width);
+                pDst[bx] = (unsigned char) pix;
+                pDst += dstScan;
+                pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan);
+            } while (--rowCount > 0);
+        }
+    } else /*DCM with ARGB*/ {
+        unsigned int *pSrc;
+
+        /* this is a number of pixels in a row, not number of bytes */
+        srcScan = srcInfo.scanStride;
+        pSrc = (unsigned int *)srcInfo.rasBase;
+
+        if (image->bitmap_bit_order == MSBFirst) {
+            do {
+                int x = 0, bx = 0;
+                unsigned int pix = 0;
+                unsigned int bit = 0x80;
+                int *srcPixel = (int *) pSrc;
+                do {
+                    if (bit == 0) {
+                        /* next word */
+                        pDst[bx++] = (unsigned char)pix;
+                        pix = 0;
+                        bit = 0x80;
+                    }
+                    if (*srcPixel++ & 0xff000000) {
+                        /* if src pixel is opaque, set the bit in the bitmap */
+                        pix |= bit;
+                    }
+                    bit >>= 1;
+                } while (++x < width);
+                /* last pixels in a row */
+                pDst[bx] = (unsigned char)pix;
+
+                pDst += dstScan;
+                pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan);
+            } while (--rowCount > 0);
+        } else {
+            do {
+                int x = 0, bx = 0;
+                unsigned int pix = 0;
+                unsigned int bit = 1;
+                int *srcPixel = (int *) pSrc;
+                do {
+                    if ((bit >> 8) != 0) {
+                        pDst[bx++] = (unsigned char)pix;
+                        pix = 0;
+                        bit = 1;
+                    }
+                    if (*srcPixel++ & 0xff000000) {
+                        /* if src pixel is opaque, set the bit in the bitmap */
+                        pix |= bit;
+                    }
+                    bit <<= 1;
+                } while (++x < width);
+                pDst[bx] = (unsigned char)pix;
+                pDst += dstScan;
+                pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan);
+            } while (--rowCount > 0);
+        }
+    }
+    SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
+    SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
+
+    xgc = XCreateGC(awt_display, xsdo->bitmask, 0L, NULL);
+    XSetForeground(awt_display, xgc, 1);
+    XSetBackground(awt_display, xgc, 0);
+    XPutImage(awt_display, xsdo->bitmask, xgc,
+              image, 0, 0, 0, 0, width, height);
+
+    XFreeGC(awt_display, xgc);
+    XDestroyImage(image);
+
+    AWT_UNLOCK();
+#endif /* !HEADLESS */
+}