--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/unix/native/libsunwjdga/dgalock.c Sun Aug 17 15:54:13 2014 +0100
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#if sparc
+
+/* #define DGA_DEBUG */
+
+#ifdef DGA_DEBUG
+#define DEBUG_PRINT(x) printf x
+#else
+#define DEBUG_PRINT(x)
+#endif
+
+#include <dga/dga.h>
+#include <unistd.h> /* ioctl */
+#include <stdlib.h>
+#include <sys/mman.h> /* mmap */
+#include <sys/visual_io.h>
+#include <string.h>
+
+/* X11 */
+#include <X11/Xlib.h>
+
+#include "jni.h"
+#include "jvm_md.h"
+#include "jdga.h"
+#include "jdgadevice.h"
+
+#include <dlfcn.h>
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+#define max(x, y) ((x) > (y) ? (x) : (y))
+
+typedef struct _SolarisDgaLibInfo SolarisDgaLibInfo;
+
+struct _SolarisDgaLibInfo {
+ /* The general (non-device specific) information */
+ unsigned long count;
+ Drawable drawable;
+ Drawable virtual_drawable;
+
+ /* The device specific memory mapping information */
+ SolarisJDgaDevInfo *devInfo;
+ SolarisJDgaWinInfo winInfo;
+};
+
+typedef Bool IsXineramaOnFunc(Display *display);
+typedef Drawable GetVirtualDrawableFunc(Display *display, Drawable drawable);
+
+#define MAX_CACHED_INFO 16
+static SolarisDgaLibInfo cachedInfo[MAX_CACHED_INFO];
+static jboolean needsSync = JNI_FALSE;
+
+#define MAX_FB_TYPES 16
+static SolarisJDgaDevInfo devicesInfo[MAX_FB_TYPES];
+
+static IsXineramaOnFunc *IsXineramaOn = NULL;
+static GetVirtualDrawableFunc GetVirtualDrawableStub;
+
+Drawable GetVirtualDrawableStub(Display *display, Drawable drawable) {
+ return drawable;
+}
+static GetVirtualDrawableFunc * GetVirtualDrawable = GetVirtualDrawableStub;
+
+static void Solaris_DGA_XineramaInit(Display *display) {
+ void * handle = NULL;
+ if (IsXineramaOn == NULL) {
+ handle = dlopen(JNI_LIB_NAME("xinerama"), RTLD_NOW);
+ if (handle != NULL) {
+ void *sym = dlsym(handle, "IsXineramaOn");
+ IsXineramaOn = (IsXineramaOnFunc *)sym;
+ if (IsXineramaOn != 0 && (*IsXineramaOn)(display)) {
+ sym = dlsym(handle, "GetVirtualDrawable");
+ if (sym != 0) {
+ GetVirtualDrawable = (GetVirtualDrawableFunc *)sym;
+ }
+ } else {
+ dlclose(handle);
+ }
+ }
+ }
+}
+
+static SolarisJDgaDevInfo * getDevInfo(Dga_drawable dgadraw) {
+ void *handle = 0;
+ struct vis_identifier visid;
+ int fd;
+ char libName[64];
+ int i;
+ SolarisJDgaDevInfo *curDevInfo = devicesInfo;
+
+ fd = dga_draw_devfd(dgadraw);
+ if (ioctl(fd, VIS_GETIDENTIFIER, &visid) != 1) {
+ /* check in the devices list */
+ for (i = 0; (i < MAX_FB_TYPES) && (curDevInfo->visidName);
+ i++, curDevInfo++) {
+ if (strcmp(visid.name, curDevInfo->visidName) == 0) {
+ /* we already have such a device, return it */
+ return curDevInfo;
+ }
+ }
+ if (i == MAX_FB_TYPES) {
+ /* we're out of slots, return NULL */
+ return NULL;
+ }
+
+ strcpy(libName, "libjdga");
+ strcat(libName, visid.name);
+ strcat(libName,".so");
+ /* we use RTLD_NOW because of bug 4032715 */
+ handle = dlopen(libName, RTLD_NOW);
+ if (handle != 0) {
+ JDgaStatus ret = JDGA_FAILED;
+ void *sym = dlsym(handle, "SolarisJDgaDevOpen");
+ if (sym != 0) {
+ curDevInfo->majorVersion = JDGALIB_MAJOR_VERSION;
+ curDevInfo->minorVersion = JDGALIB_MINOR_VERSION;
+ ret = (*(SolarisJDgaDevOpenFunc *)sym)(curDevInfo);
+ }
+ if (ret == JDGA_SUCCESS) {
+ curDevInfo->visidName = strdup(visid.name);
+ return curDevInfo;
+ }
+ dlclose(handle);
+ }
+ }
+ return NULL;
+}
+static int
+mmap_dgaDev(SolarisDgaLibInfo *libInfo, Dga_drawable dgadraw)
+{
+
+ if (!libInfo->devInfo) {
+ libInfo->devInfo = getDevInfo(dgadraw);
+ if (!libInfo->devInfo) {
+ return JDGA_FAILED;
+ }
+ }
+ return (*libInfo->devInfo->function->winopen)(&(libInfo->winInfo));
+}
+
+static void
+unmap_dgaDev(SolarisDgaLibInfo *pDevInfo)
+{
+ DEBUG_PRINT(("winclose() called\n"));
+ (*pDevInfo->devInfo->function->winclose)(&(pDevInfo->winInfo));
+}
+
+static jboolean
+Solaris_DGA_Available(Display *display)
+{
+ Window root;
+ int screen;
+ Dga_drawable dgaDrawable;
+ SolarisJDgaDevInfo * devinfo;
+
+ /* return true if any screen supports DGA and we
+ have a library for this type of framebuffer */
+ for (screen = 0; screen < XScreenCount(display); screen++) {
+ root = RootWindow(display, screen);
+
+ dgaDrawable = XDgaGrabDrawable(display, root);
+ if (dgaDrawable != 0) {
+ devinfo = getDevInfo(dgaDrawable);
+ XDgaUnGrabDrawable(dgaDrawable);
+ if (devinfo != NULL) {
+ return JNI_TRUE;
+ }
+ }
+ }
+ return JNI_FALSE;
+}
+
+static JDgaLibInitFunc Solaris_DGA_LibInit;
+static JDgaGetLockFunc Solaris_DGA_GetLock;
+static JDgaReleaseLockFunc Solaris_DGA_ReleaseLock;
+static JDgaXRequestSentFunc Solaris_DGA_XRequestSent;
+static JDgaLibDisposeFunc Solaris_DGA_LibDispose;
+static int firstInitDone = 0;
+
+#pragma weak JDgaLibInit = Solaris_DGA_LibInit
+
+static JDgaStatus
+Solaris_DGA_LibInit(JNIEnv *env, JDgaLibInfo *ppInfo)
+{
+ /* Note: DGA_INIT can be called multiple times according to docs */
+ DEBUG_PRINT(("DGA_INIT called\n"));
+ DGA_INIT();
+
+ if (!Solaris_DGA_Available(ppInfo->display)) {
+ return JDGA_FAILED;
+ }
+ Solaris_DGA_XineramaInit(ppInfo->display);
+
+ ppInfo->pGetLock = Solaris_DGA_GetLock;
+ ppInfo->pReleaseLock = Solaris_DGA_ReleaseLock;
+ ppInfo->pXRequestSent = Solaris_DGA_XRequestSent;
+ ppInfo->pLibDispose = Solaris_DGA_LibDispose;
+
+ return JDGA_SUCCESS;
+}
+
+static JDgaStatus
+Solaris_DGA_GetLock(JNIEnv *env, Display *display, void **dgaDev,
+ Drawable drawable, JDgaSurfaceInfo *pSurface,
+ jint lox, jint loy, jint hix, jint hiy)
+{
+ SolarisDgaLibInfo *pDevInfo;
+ SolarisDgaLibInfo *pCachedInfo = cachedInfo;
+ int vis;
+ int dlox, dloy, dhix, dhiy;
+ int i;
+ int type, site;
+ unsigned long k;
+ Drawable prev_virtual_drawable = 0;
+ Dga_drawable dgaDrawable;
+
+ if (*dgaDev) {
+ if (((SolarisDgaLibInfo *)(*dgaDev))->drawable != drawable) {
+ *dgaDev = 0;
+ }
+ }
+
+ if (*dgaDev == 0) {
+ pCachedInfo = cachedInfo;
+ for (i = 0 ; (i < MAX_CACHED_INFO) && (pCachedInfo->drawable) ;
+ i++, pCachedInfo++) {
+ if (pCachedInfo->drawable == drawable) {
+ *dgaDev = pCachedInfo;
+ break;
+ }
+ }
+ if (*dgaDev == 0) {
+ if (i < MAX_CACHED_INFO) { /* slot can be used for new info */
+ *dgaDev = pCachedInfo;
+ } else {
+ pCachedInfo = cachedInfo;
+ /* find the least used slot but does not handle an overflow of
+ the counter */
+ for (i = 0, k = 0xffffffff; i < MAX_CACHED_INFO ;
+ i++, pCachedInfo++) {
+ if (k > pCachedInfo->count) {
+ k = pCachedInfo->count;
+ *dgaDev = pCachedInfo;
+ }
+ pCachedInfo->count = 0; /* reset all counters */
+ }
+ pCachedInfo = *dgaDev;
+ if (pCachedInfo->winInfo.dgaDraw != 0) {
+ XDgaUnGrabDrawable(pCachedInfo->winInfo.dgaDraw);
+ }
+ pCachedInfo->winInfo.dgaDraw = 0;
+ /* the slot might be used for another device */
+ pCachedInfo->devInfo = 0;
+ }
+ }
+ }
+
+ pDevInfo = *dgaDev;
+ pDevInfo->drawable = drawable;
+
+ prev_virtual_drawable = pDevInfo->virtual_drawable;
+ pDevInfo->virtual_drawable = GetVirtualDrawable(display, drawable);
+ if (pDevInfo->virtual_drawable == NULL) {
+ /* this usually means that the drawable is spanned across
+ screens in xinerama mode - we can't handle this for now */
+ return JDGA_FAILED;
+ } else {
+ /* check if the drawable has been moved to another screen
+ since last time */
+ if (pDevInfo->winInfo.dgaDraw != 0 &&
+ pDevInfo->virtual_drawable != prev_virtual_drawable) {
+ XDgaUnGrabDrawable(pDevInfo->winInfo.dgaDraw);
+ pDevInfo->winInfo.dgaDraw = 0;
+ }
+ }
+
+ pDevInfo->count++;
+
+ if (pDevInfo->winInfo.dgaDraw == 0) {
+ pDevInfo->winInfo.dgaDraw = XDgaGrabDrawable(display, pDevInfo->virtual_drawable);
+ if (pDevInfo->winInfo.dgaDraw == 0) {
+ DEBUG_PRINT(("DgaGrabDrawable failed for 0x%08x\n", drawable));
+ return JDGA_UNAVAILABLE;
+ }
+ type = dga_draw_type(pDevInfo->winInfo.dgaDraw);
+ if (type != DGA_DRAW_PIXMAP &&
+ mmap_dgaDev(pDevInfo, pDevInfo->winInfo.dgaDraw) != JDGA_SUCCESS) {
+ DEBUG_PRINT(("memory map failed for 0x%08x (depth = %d)\n",
+ drawable, dga_draw_depth(pDevInfo->winInfo.dgaDraw)));
+ XDgaUnGrabDrawable(pDevInfo->winInfo.dgaDraw);
+ pDevInfo->winInfo.dgaDraw = 0;
+ return JDGA_UNAVAILABLE;
+ }
+ } else {
+ type = dga_draw_type(pDevInfo->winInfo.dgaDraw);
+ }
+
+ if (needsSync) {
+ XSync(display, False);
+ needsSync = JNI_FALSE;
+ }
+
+ dgaDrawable = pDevInfo->winInfo.dgaDraw;
+
+ DGA_DRAW_LOCK(dgaDrawable, -1);
+
+ site = dga_draw_site(dgaDrawable);
+ if (type == DGA_DRAW_PIXMAP) {
+ if (site == DGA_SITE_SYSTEM) {
+ pDevInfo->winInfo.mapDepth = dga_draw_depth(dgaDrawable);
+ pDevInfo->winInfo.mapAddr = dga_draw_address(dgaDrawable);
+ dga_draw_bbox(dgaDrawable, &dlox, &dloy, &dhix, &dhiy);
+ pDevInfo->winInfo.mapWidth = dhix;
+ pDevInfo->winInfo.mapHeight = dhiy;
+ if (pDevInfo->winInfo.mapDepth == 8) {
+ pDevInfo->winInfo.mapLineStride = dga_draw_linebytes(dgaDrawable);
+ pDevInfo->winInfo.mapPixelStride = 1;
+ } else {
+ pDevInfo->winInfo.mapLineStride = dga_draw_linebytes(dgaDrawable)/4;
+ pDevInfo->winInfo.mapPixelStride = 4;
+ }
+ } else {
+ XDgaUnGrabDrawable(dgaDrawable);
+ pDevInfo->winInfo.dgaDraw = 0;
+ return JDGA_UNAVAILABLE;
+ }
+ } else {
+ if (site == DGA_SITE_NULL) {
+ DEBUG_PRINT(("zombie drawable = 0x%08x\n", dgaDrawable));
+ DGA_DRAW_UNLOCK(dgaDrawable);
+ unmap_dgaDev(pDevInfo);
+ XDgaUnGrabDrawable(dgaDrawable);
+ pDevInfo->winInfo.dgaDraw = 0;
+ return JDGA_UNAVAILABLE;
+ }
+ dga_draw_bbox(dgaDrawable, &dlox, &dloy, &dhix, &dhiy);
+ }
+
+ /* get the screen address of the drawable */
+ dhix += dlox;
+ dhiy += dloy;
+ DEBUG_PRINT(("window at (%d, %d) => (%d, %d)\n", dlox, dloy, dhix, dhiy));
+ pSurface->window.lox = dlox;
+ pSurface->window.loy = dloy;
+ pSurface->window.hix = dhix;
+ pSurface->window.hiy = dhiy;
+
+ /* translate rendering coordinates relative to device bbox */
+ lox += dlox;
+ loy += dloy;
+ hix += dlox;
+ hiy += dloy;
+ DEBUG_PRINT(("render at (%d, %d) => (%d, %d)\n", lox, loy, hix, hiy));
+
+ vis = dga_draw_visibility(dgaDrawable);
+ switch (vis) {
+ case DGA_VIS_UNOBSCURED:
+ pSurface->visible.lox = max(dlox, lox);
+ pSurface->visible.loy = max(dloy, loy);
+ pSurface->visible.hix = min(dhix, hix);
+ pSurface->visible.hiy = min(dhiy, hiy);
+ DEBUG_PRINT(("unobscured vis at (%d, %d) => (%d, %d)\n",
+ pSurface->visible.lox,
+ pSurface->visible.loy,
+ pSurface->visible.hix,
+ pSurface->visible.hiy));
+ break;
+ case DGA_VIS_PARTIALLY_OBSCURED: {
+ /*
+ * fix for #4305271
+ * the dga_draw_clipinfo call returns the clipping bounds
+ * in short ints, but use only full size ints for all comparisons.
+ */
+ short *ptr;
+ int x0, y0, x1, y1;
+ int cliplox, cliploy, cliphix, cliphiy;
+
+ /*
+ * iterate to find out whether the clipped blit draws to a
+ * single clipping rectangle
+ */
+ cliplox = cliphix = lox;
+ cliploy = cliphiy = loy;
+ ptr = dga_draw_clipinfo(dgaDrawable);
+ while (*ptr != DGA_Y_EOL) {
+ y0 = *ptr++;
+ y1 = *ptr++;
+ DEBUG_PRINT(("DGA y range loy=%d hiy=%d\n", y0, y1));
+ if (y0 < loy) {
+ y0 = loy;
+ }
+ if (y1 > hiy) {
+ y1 = hiy;
+ }
+ while (*ptr != DGA_X_EOL) {
+ x0 = *ptr++;
+ x1 = *ptr++;
+ DEBUG_PRINT((" DGA x range lox=%d hix=%d\n", x0, x1));
+ if (x0 < lox) {
+ x0 = lox;
+ }
+ if (x1 > hix) {
+ x1 = hix;
+ }
+ if (x0 < x1 && y0 < y1) {
+ if (cliploy == cliphiy) {
+ /* First rectangle intersection */
+ cliplox = x0;
+ cliploy = y0;
+ cliphix = x1;
+ cliphiy = y1;
+ } else {
+ /* Can we merge this rect with previous? */
+ if (cliplox == x0 && cliphix == x1 &&
+ cliploy <= y1 && cliphiy >= y0)
+ {
+ /* X ranges match, Y ranges touch */
+ /* => absorb the Y ranges together */
+ cliploy = min(cliploy, y0);
+ cliphiy = max(cliphiy, y1);
+ } else if (cliploy == y0 && cliphiy == y1 &&
+ cliplox <= x1 && cliphix >= x0)
+ {
+ /* Y ranges match, X ranges touch */
+ /* => Absorb the X ranges together */
+ cliplox = min(cliplox, x0);
+ cliphix = max(cliphix, x1);
+ } else {
+ /* Assertion: any other combination */
+ /* means non-rectangular intersect */
+ DGA_DRAW_UNLOCK(dgaDrawable);
+ return JDGA_FAILED;
+ }
+ }
+ }
+ }
+ ptr++; /* advance past DGA_X_EOL */
+ }
+ DEBUG_PRINT(("DGA drawable fits\n"));
+ pSurface->visible.lox = cliplox;
+ pSurface->visible.loy = cliploy;
+ pSurface->visible.hix = cliphix;
+ pSurface->visible.hiy = cliphiy;
+ break;
+ }
+ case DGA_VIS_FULLY_OBSCURED:
+ pSurface->visible.lox =
+ pSurface->visible.hix = lox;
+ pSurface->visible.loy =
+ pSurface->visible.hiy = loy;
+ DEBUG_PRINT(("fully obscured vis\n"));
+ break;
+ default:
+ DEBUG_PRINT(("unknown visibility = %d!\n", vis));
+ DGA_DRAW_UNLOCK(dgaDrawable);
+ return JDGA_FAILED;
+ }
+
+ pSurface->basePtr = pDevInfo->winInfo.mapAddr;
+ pSurface->surfaceScan = pDevInfo->winInfo.mapLineStride;
+ pSurface->surfaceWidth = pDevInfo->winInfo.mapWidth;
+ pSurface->surfaceHeight = pDevInfo->winInfo.mapHeight;
+ pSurface->surfaceDepth = pDevInfo->winInfo.mapDepth;
+
+ return JDGA_SUCCESS;
+}
+
+static JDgaStatus
+Solaris_DGA_ReleaseLock(JNIEnv *env, void *dgaDev, Drawable drawable)
+{
+ SolarisDgaLibInfo *pDevInfo = (SolarisDgaLibInfo *) dgaDev;
+
+ if (pDevInfo != 0 && pDevInfo->drawable == drawable &&
+ pDevInfo->winInfo.dgaDraw != 0) {
+ DGA_DRAW_UNLOCK(pDevInfo->winInfo.dgaDraw);
+ }
+ return JDGA_SUCCESS;
+}
+
+static void
+Solaris_DGA_XRequestSent(JNIEnv *env, void *dgaDev, Drawable drawable)
+{
+ needsSync = JNI_TRUE;
+}
+
+static void
+Solaris_DGA_LibDispose(JNIEnv *env)
+{
+ SolarisDgaLibInfo *pCachedInfo = cachedInfo;
+ SolarisJDgaDevInfo *curDevInfo = devicesInfo;
+ int i;
+
+ for (i = 0 ; (i < MAX_CACHED_INFO) && (pCachedInfo->drawable) ;
+ i++, pCachedInfo++) {
+ if (pCachedInfo->winInfo.dgaDraw != 0) {
+ if (dga_draw_type(pCachedInfo->winInfo.dgaDraw) == DGA_DRAW_WINDOW &&
+ pCachedInfo->winInfo.mapDepth != 0) {
+ unmap_dgaDev(pCachedInfo);
+ }
+ XDgaUnGrabDrawable(pCachedInfo->winInfo.dgaDraw);
+ pCachedInfo->winInfo.dgaDraw = 0;
+ }
+ }
+ for (i = 0; (i < MAX_FB_TYPES) && (curDevInfo->visidName);
+ i++, curDevInfo++) {
+ curDevInfo->function->devclose(curDevInfo);
+ free(curDevInfo->visidName);
+ }
+}
+#endif