Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/jdga/dgalock.c
32287 views
/*1* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#if sparc2627/* #define DGA_DEBUG */2829#ifdef DGA_DEBUG30#define DEBUG_PRINT(x) printf x31#else32#define DEBUG_PRINT(x)33#endif3435#include <dga/dga.h>36#include <unistd.h> /* ioctl */37#include <stdlib.h>38#include <sys/mman.h> /* mmap */39#include <sys/visual_io.h>40#include <string.h>4142/* X11 */43#include <X11/Xlib.h>4445#include "jni.h"46#include "jvm_md.h"47#include "jdga.h"48#include "jdgadevice.h"4950#include <dlfcn.h>5152#define min(x, y) ((x) < (y) ? (x) : (y))53#define max(x, y) ((x) > (y) ? (x) : (y))5455typedef struct _SolarisDgaLibInfo SolarisDgaLibInfo;5657struct _SolarisDgaLibInfo {58/* The general (non-device specific) information */59unsigned long count;60Drawable drawable;61Drawable virtual_drawable;6263/* The device specific memory mapping information */64SolarisJDgaDevInfo *devInfo;65SolarisJDgaWinInfo winInfo;66};6768typedef Bool IsXineramaOnFunc(Display *display);69typedef Drawable GetVirtualDrawableFunc(Display *display, Drawable drawable);7071#define MAX_CACHED_INFO 1672static SolarisDgaLibInfo cachedInfo[MAX_CACHED_INFO];73static jboolean needsSync = JNI_FALSE;7475#define MAX_FB_TYPES 1676static SolarisJDgaDevInfo devicesInfo[MAX_FB_TYPES];7778static IsXineramaOnFunc *IsXineramaOn = NULL;79static GetVirtualDrawableFunc GetVirtualDrawableStub;8081Drawable GetVirtualDrawableStub(Display *display, Drawable drawable) {82return drawable;83}84static GetVirtualDrawableFunc * GetVirtualDrawable = GetVirtualDrawableStub;8586static void Solaris_DGA_XineramaInit(Display *display) {87void * handle = NULL;88if (IsXineramaOn == NULL) {89handle = dlopen(JNI_LIB_NAME("xinerama"), RTLD_NOW);90if (handle != NULL) {91void *sym = dlsym(handle, "IsXineramaOn");92IsXineramaOn = (IsXineramaOnFunc *)sym;93if (IsXineramaOn != 0 && (*IsXineramaOn)(display)) {94sym = dlsym(handle, "GetVirtualDrawable");95if (sym != 0) {96GetVirtualDrawable = (GetVirtualDrawableFunc *)sym;97}98} else {99dlclose(handle);100}101}102}103}104105static SolarisJDgaDevInfo * getDevInfo(Dga_drawable dgadraw) {106void *handle = 0;107struct vis_identifier visid;108int fd;109char libName[64];110int i;111SolarisJDgaDevInfo *curDevInfo = devicesInfo;112113fd = dga_draw_devfd(dgadraw);114if (ioctl(fd, VIS_GETIDENTIFIER, &visid) != 1) {115/* check in the devices list */116for (i = 0; (i < MAX_FB_TYPES) && (curDevInfo->visidName);117i++, curDevInfo++) {118if (strcmp(visid.name, curDevInfo->visidName) == 0) {119/* we already have such a device, return it */120return curDevInfo;121}122}123if (i == MAX_FB_TYPES) {124/* we're out of slots, return NULL */125return NULL;126}127128strcpy(libName, "libjdga");129strcat(libName, visid.name);130strcat(libName,".so");131/* we use RTLD_NOW because of bug 4032715 */132handle = dlopen(libName, RTLD_NOW);133if (handle != 0) {134JDgaStatus ret = JDGA_FAILED;135void *sym = dlsym(handle, "SolarisJDgaDevOpen");136if (sym != 0) {137curDevInfo->majorVersion = JDGALIB_MAJOR_VERSION;138curDevInfo->minorVersion = JDGALIB_MINOR_VERSION;139ret = (*(SolarisJDgaDevOpenFunc *)sym)(curDevInfo);140}141if (ret == JDGA_SUCCESS) {142curDevInfo->visidName = strdup(visid.name);143return curDevInfo;144}145dlclose(handle);146}147}148return NULL;149}150static int151mmap_dgaDev(SolarisDgaLibInfo *libInfo, Dga_drawable dgadraw)152{153154if (!libInfo->devInfo) {155libInfo->devInfo = getDevInfo(dgadraw);156if (!libInfo->devInfo) {157return JDGA_FAILED;158}159}160return (*libInfo->devInfo->function->winopen)(&(libInfo->winInfo));161}162163static void164unmap_dgaDev(SolarisDgaLibInfo *pDevInfo)165{166DEBUG_PRINT(("winclose() called\n"));167(*pDevInfo->devInfo->function->winclose)(&(pDevInfo->winInfo));168}169170static jboolean171Solaris_DGA_Available(Display *display)172{173Window root;174int screen;175Dga_drawable dgaDrawable;176SolarisJDgaDevInfo * devinfo;177178/* return true if any screen supports DGA and we179have a library for this type of framebuffer */180for (screen = 0; screen < XScreenCount(display); screen++) {181root = RootWindow(display, screen);182183dgaDrawable = XDgaGrabDrawable(display, root);184if (dgaDrawable != 0) {185devinfo = getDevInfo(dgaDrawable);186XDgaUnGrabDrawable(dgaDrawable);187if (devinfo != NULL) {188return JNI_TRUE;189}190}191}192return JNI_FALSE;193}194195static JDgaLibInitFunc Solaris_DGA_LibInit;196static JDgaGetLockFunc Solaris_DGA_GetLock;197static JDgaReleaseLockFunc Solaris_DGA_ReleaseLock;198static JDgaXRequestSentFunc Solaris_DGA_XRequestSent;199static JDgaLibDisposeFunc Solaris_DGA_LibDispose;200static int firstInitDone = 0;201202#pragma weak JDgaLibInit = Solaris_DGA_LibInit203204static JDgaStatus205Solaris_DGA_LibInit(JNIEnv *env, JDgaLibInfo *ppInfo)206{207/* Note: DGA_INIT can be called multiple times according to docs */208DEBUG_PRINT(("DGA_INIT called\n"));209DGA_INIT();210211if (!Solaris_DGA_Available(ppInfo->display)) {212return JDGA_FAILED;213}214Solaris_DGA_XineramaInit(ppInfo->display);215216ppInfo->pGetLock = Solaris_DGA_GetLock;217ppInfo->pReleaseLock = Solaris_DGA_ReleaseLock;218ppInfo->pXRequestSent = Solaris_DGA_XRequestSent;219ppInfo->pLibDispose = Solaris_DGA_LibDispose;220221return JDGA_SUCCESS;222}223224static JDgaStatus225Solaris_DGA_GetLock(JNIEnv *env, Display *display, void **dgaDev,226Drawable drawable, JDgaSurfaceInfo *pSurface,227jint lox, jint loy, jint hix, jint hiy)228{229SolarisDgaLibInfo *pDevInfo;230SolarisDgaLibInfo *pCachedInfo = cachedInfo;231int vis;232int dlox, dloy, dhix, dhiy;233int i;234int type, site;235unsigned long k;236Drawable prev_virtual_drawable = 0;237Dga_drawable dgaDrawable;238239if (*dgaDev) {240if (((SolarisDgaLibInfo *)(*dgaDev))->drawable != drawable) {241*dgaDev = 0;242}243}244245if (*dgaDev == 0) {246pCachedInfo = cachedInfo;247for (i = 0 ; (i < MAX_CACHED_INFO) && (pCachedInfo->drawable) ;248i++, pCachedInfo++) {249if (pCachedInfo->drawable == drawable) {250*dgaDev = pCachedInfo;251break;252}253}254if (*dgaDev == 0) {255if (i < MAX_CACHED_INFO) { /* slot can be used for new info */256*dgaDev = pCachedInfo;257} else {258pCachedInfo = cachedInfo;259/* find the least used slot but does not handle an overflow of260the counter */261for (i = 0, k = 0xffffffff; i < MAX_CACHED_INFO ;262i++, pCachedInfo++) {263if (k > pCachedInfo->count) {264k = pCachedInfo->count;265*dgaDev = pCachedInfo;266}267pCachedInfo->count = 0; /* reset all counters */268}269pCachedInfo = *dgaDev;270if (pCachedInfo->winInfo.dgaDraw != 0) {271XDgaUnGrabDrawable(pCachedInfo->winInfo.dgaDraw);272}273pCachedInfo->winInfo.dgaDraw = 0;274/* the slot might be used for another device */275pCachedInfo->devInfo = 0;276}277}278}279280pDevInfo = *dgaDev;281pDevInfo->drawable = drawable;282283prev_virtual_drawable = pDevInfo->virtual_drawable;284pDevInfo->virtual_drawable = GetVirtualDrawable(display, drawable);285if (pDevInfo->virtual_drawable == NULL) {286/* this usually means that the drawable is spanned across287screens in xinerama mode - we can't handle this for now */288return JDGA_FAILED;289} else {290/* check if the drawable has been moved to another screen291since last time */292if (pDevInfo->winInfo.dgaDraw != 0 &&293pDevInfo->virtual_drawable != prev_virtual_drawable) {294XDgaUnGrabDrawable(pDevInfo->winInfo.dgaDraw);295pDevInfo->winInfo.dgaDraw = 0;296}297}298299pDevInfo->count++;300301if (pDevInfo->winInfo.dgaDraw == 0) {302pDevInfo->winInfo.dgaDraw = XDgaGrabDrawable(display, pDevInfo->virtual_drawable);303if (pDevInfo->winInfo.dgaDraw == 0) {304DEBUG_PRINT(("DgaGrabDrawable failed for 0x%08x\n", drawable));305return JDGA_UNAVAILABLE;306}307type = dga_draw_type(pDevInfo->winInfo.dgaDraw);308if (type != DGA_DRAW_PIXMAP &&309mmap_dgaDev(pDevInfo, pDevInfo->winInfo.dgaDraw) != JDGA_SUCCESS) {310DEBUG_PRINT(("memory map failed for 0x%08x (depth = %d)\n",311drawable, dga_draw_depth(pDevInfo->winInfo.dgaDraw)));312XDgaUnGrabDrawable(pDevInfo->winInfo.dgaDraw);313pDevInfo->winInfo.dgaDraw = 0;314return JDGA_UNAVAILABLE;315}316} else {317type = dga_draw_type(pDevInfo->winInfo.dgaDraw);318}319320if (needsSync) {321XSync(display, False);322needsSync = JNI_FALSE;323}324325dgaDrawable = pDevInfo->winInfo.dgaDraw;326327DGA_DRAW_LOCK(dgaDrawable, -1);328329site = dga_draw_site(dgaDrawable);330if (type == DGA_DRAW_PIXMAP) {331if (site == DGA_SITE_SYSTEM) {332pDevInfo->winInfo.mapDepth = dga_draw_depth(dgaDrawable);333pDevInfo->winInfo.mapAddr = dga_draw_address(dgaDrawable);334dga_draw_bbox(dgaDrawable, &dlox, &dloy, &dhix, &dhiy);335pDevInfo->winInfo.mapWidth = dhix;336pDevInfo->winInfo.mapHeight = dhiy;337if (pDevInfo->winInfo.mapDepth == 8) {338pDevInfo->winInfo.mapLineStride = dga_draw_linebytes(dgaDrawable);339pDevInfo->winInfo.mapPixelStride = 1;340} else {341pDevInfo->winInfo.mapLineStride = dga_draw_linebytes(dgaDrawable)/4;342pDevInfo->winInfo.mapPixelStride = 4;343}344} else {345XDgaUnGrabDrawable(dgaDrawable);346pDevInfo->winInfo.dgaDraw = 0;347return JDGA_UNAVAILABLE;348}349} else {350if (site == DGA_SITE_NULL) {351DEBUG_PRINT(("zombie drawable = 0x%08x\n", dgaDrawable));352DGA_DRAW_UNLOCK(dgaDrawable);353unmap_dgaDev(pDevInfo);354XDgaUnGrabDrawable(dgaDrawable);355pDevInfo->winInfo.dgaDraw = 0;356return JDGA_UNAVAILABLE;357}358dga_draw_bbox(dgaDrawable, &dlox, &dloy, &dhix, &dhiy);359}360361/* get the screen address of the drawable */362dhix += dlox;363dhiy += dloy;364DEBUG_PRINT(("window at (%d, %d) => (%d, %d)\n", dlox, dloy, dhix, dhiy));365pSurface->window.lox = dlox;366pSurface->window.loy = dloy;367pSurface->window.hix = dhix;368pSurface->window.hiy = dhiy;369370/* translate rendering coordinates relative to device bbox */371lox += dlox;372loy += dloy;373hix += dlox;374hiy += dloy;375DEBUG_PRINT(("render at (%d, %d) => (%d, %d)\n", lox, loy, hix, hiy));376377vis = dga_draw_visibility(dgaDrawable);378switch (vis) {379case DGA_VIS_UNOBSCURED:380pSurface->visible.lox = max(dlox, lox);381pSurface->visible.loy = max(dloy, loy);382pSurface->visible.hix = min(dhix, hix);383pSurface->visible.hiy = min(dhiy, hiy);384DEBUG_PRINT(("unobscured vis at (%d, %d) => (%d, %d)\n",385pSurface->visible.lox,386pSurface->visible.loy,387pSurface->visible.hix,388pSurface->visible.hiy));389break;390case DGA_VIS_PARTIALLY_OBSCURED: {391/*392* fix for #4305271393* the dga_draw_clipinfo call returns the clipping bounds394* in short ints, but use only full size ints for all comparisons.395*/396short *ptr;397int x0, y0, x1, y1;398int cliplox, cliploy, cliphix, cliphiy;399400/*401* iterate to find out whether the clipped blit draws to a402* single clipping rectangle403*/404cliplox = cliphix = lox;405cliploy = cliphiy = loy;406ptr = dga_draw_clipinfo(dgaDrawable);407while (*ptr != DGA_Y_EOL) {408y0 = *ptr++;409y1 = *ptr++;410DEBUG_PRINT(("DGA y range loy=%d hiy=%d\n", y0, y1));411if (y0 < loy) {412y0 = loy;413}414if (y1 > hiy) {415y1 = hiy;416}417while (*ptr != DGA_X_EOL) {418x0 = *ptr++;419x1 = *ptr++;420DEBUG_PRINT((" DGA x range lox=%d hix=%d\n", x0, x1));421if (x0 < lox) {422x0 = lox;423}424if (x1 > hix) {425x1 = hix;426}427if (x0 < x1 && y0 < y1) {428if (cliploy == cliphiy) {429/* First rectangle intersection */430cliplox = x0;431cliploy = y0;432cliphix = x1;433cliphiy = y1;434} else {435/* Can we merge this rect with previous? */436if (cliplox == x0 && cliphix == x1 &&437cliploy <= y1 && cliphiy >= y0)438{439/* X ranges match, Y ranges touch */440/* => absorb the Y ranges together */441cliploy = min(cliploy, y0);442cliphiy = max(cliphiy, y1);443} else if (cliploy == y0 && cliphiy == y1 &&444cliplox <= x1 && cliphix >= x0)445{446/* Y ranges match, X ranges touch */447/* => Absorb the X ranges together */448cliplox = min(cliplox, x0);449cliphix = max(cliphix, x1);450} else {451/* Assertion: any other combination */452/* means non-rectangular intersect */453DGA_DRAW_UNLOCK(dgaDrawable);454return JDGA_FAILED;455}456}457}458}459ptr++; /* advance past DGA_X_EOL */460}461DEBUG_PRINT(("DGA drawable fits\n"));462pSurface->visible.lox = cliplox;463pSurface->visible.loy = cliploy;464pSurface->visible.hix = cliphix;465pSurface->visible.hiy = cliphiy;466break;467}468case DGA_VIS_FULLY_OBSCURED:469pSurface->visible.lox =470pSurface->visible.hix = lox;471pSurface->visible.loy =472pSurface->visible.hiy = loy;473DEBUG_PRINT(("fully obscured vis\n"));474break;475default:476DEBUG_PRINT(("unknown visibility = %d!\n", vis));477DGA_DRAW_UNLOCK(dgaDrawable);478return JDGA_FAILED;479}480481pSurface->basePtr = pDevInfo->winInfo.mapAddr;482pSurface->surfaceScan = pDevInfo->winInfo.mapLineStride;483pSurface->surfaceWidth = pDevInfo->winInfo.mapWidth;484pSurface->surfaceHeight = pDevInfo->winInfo.mapHeight;485pSurface->surfaceDepth = pDevInfo->winInfo.mapDepth;486487return JDGA_SUCCESS;488}489490static JDgaStatus491Solaris_DGA_ReleaseLock(JNIEnv *env, void *dgaDev, Drawable drawable)492{493SolarisDgaLibInfo *pDevInfo = (SolarisDgaLibInfo *) dgaDev;494495if (pDevInfo != 0 && pDevInfo->drawable == drawable &&496pDevInfo->winInfo.dgaDraw != 0) {497DGA_DRAW_UNLOCK(pDevInfo->winInfo.dgaDraw);498}499return JDGA_SUCCESS;500}501502static void503Solaris_DGA_XRequestSent(JNIEnv *env, void *dgaDev, Drawable drawable)504{505needsSync = JNI_TRUE;506}507508static void509Solaris_DGA_LibDispose(JNIEnv *env)510{511SolarisDgaLibInfo *pCachedInfo = cachedInfo;512SolarisJDgaDevInfo *curDevInfo = devicesInfo;513int i;514515for (i = 0 ; (i < MAX_CACHED_INFO) && (pCachedInfo->drawable) ;516i++, pCachedInfo++) {517if (pCachedInfo->winInfo.dgaDraw != 0) {518if (dga_draw_type(pCachedInfo->winInfo.dgaDraw) == DGA_DRAW_WINDOW &&519pCachedInfo->winInfo.mapDepth != 0) {520unmap_dgaDev(pCachedInfo);521}522XDgaUnGrabDrawable(pCachedInfo->winInfo.dgaDraw);523pCachedInfo->winInfo.dgaDraw = 0;524}525}526for (i = 0; (i < MAX_FB_TYPES) && (curDevInfo->visidName);527i++, curDevInfo++) {528curDevInfo->function->devclose(curDevInfo);529free(curDevInfo->visidName);530}531}532#endif533534535