Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/jdga/dgalock.c
32287 views
1
/*
2
* Copyright (c) 1998, 2012, 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
#if sparc
27
28
/* #define DGA_DEBUG */
29
30
#ifdef DGA_DEBUG
31
#define DEBUG_PRINT(x) printf x
32
#else
33
#define DEBUG_PRINT(x)
34
#endif
35
36
#include <dga/dga.h>
37
#include <unistd.h> /* ioctl */
38
#include <stdlib.h>
39
#include <sys/mman.h> /* mmap */
40
#include <sys/visual_io.h>
41
#include <string.h>
42
43
/* X11 */
44
#include <X11/Xlib.h>
45
46
#include "jni.h"
47
#include "jvm_md.h"
48
#include "jdga.h"
49
#include "jdgadevice.h"
50
51
#include <dlfcn.h>
52
53
#define min(x, y) ((x) < (y) ? (x) : (y))
54
#define max(x, y) ((x) > (y) ? (x) : (y))
55
56
typedef struct _SolarisDgaLibInfo SolarisDgaLibInfo;
57
58
struct _SolarisDgaLibInfo {
59
/* The general (non-device specific) information */
60
unsigned long count;
61
Drawable drawable;
62
Drawable virtual_drawable;
63
64
/* The device specific memory mapping information */
65
SolarisJDgaDevInfo *devInfo;
66
SolarisJDgaWinInfo winInfo;
67
};
68
69
typedef Bool IsXineramaOnFunc(Display *display);
70
typedef Drawable GetVirtualDrawableFunc(Display *display, Drawable drawable);
71
72
#define MAX_CACHED_INFO 16
73
static SolarisDgaLibInfo cachedInfo[MAX_CACHED_INFO];
74
static jboolean needsSync = JNI_FALSE;
75
76
#define MAX_FB_TYPES 16
77
static SolarisJDgaDevInfo devicesInfo[MAX_FB_TYPES];
78
79
static IsXineramaOnFunc *IsXineramaOn = NULL;
80
static GetVirtualDrawableFunc GetVirtualDrawableStub;
81
82
Drawable GetVirtualDrawableStub(Display *display, Drawable drawable) {
83
return drawable;
84
}
85
static GetVirtualDrawableFunc * GetVirtualDrawable = GetVirtualDrawableStub;
86
87
static void Solaris_DGA_XineramaInit(Display *display) {
88
void * handle = NULL;
89
if (IsXineramaOn == NULL) {
90
handle = dlopen(JNI_LIB_NAME("xinerama"), RTLD_NOW);
91
if (handle != NULL) {
92
void *sym = dlsym(handle, "IsXineramaOn");
93
IsXineramaOn = (IsXineramaOnFunc *)sym;
94
if (IsXineramaOn != 0 && (*IsXineramaOn)(display)) {
95
sym = dlsym(handle, "GetVirtualDrawable");
96
if (sym != 0) {
97
GetVirtualDrawable = (GetVirtualDrawableFunc *)sym;
98
}
99
} else {
100
dlclose(handle);
101
}
102
}
103
}
104
}
105
106
static SolarisJDgaDevInfo * getDevInfo(Dga_drawable dgadraw) {
107
void *handle = 0;
108
struct vis_identifier visid;
109
int fd;
110
char libName[64];
111
int i;
112
SolarisJDgaDevInfo *curDevInfo = devicesInfo;
113
114
fd = dga_draw_devfd(dgadraw);
115
if (ioctl(fd, VIS_GETIDENTIFIER, &visid) != 1) {
116
/* check in the devices list */
117
for (i = 0; (i < MAX_FB_TYPES) && (curDevInfo->visidName);
118
i++, curDevInfo++) {
119
if (strcmp(visid.name, curDevInfo->visidName) == 0) {
120
/* we already have such a device, return it */
121
return curDevInfo;
122
}
123
}
124
if (i == MAX_FB_TYPES) {
125
/* we're out of slots, return NULL */
126
return NULL;
127
}
128
129
strcpy(libName, "libjdga");
130
strcat(libName, visid.name);
131
strcat(libName,".so");
132
/* we use RTLD_NOW because of bug 4032715 */
133
handle = dlopen(libName, RTLD_NOW);
134
if (handle != 0) {
135
JDgaStatus ret = JDGA_FAILED;
136
void *sym = dlsym(handle, "SolarisJDgaDevOpen");
137
if (sym != 0) {
138
curDevInfo->majorVersion = JDGALIB_MAJOR_VERSION;
139
curDevInfo->minorVersion = JDGALIB_MINOR_VERSION;
140
ret = (*(SolarisJDgaDevOpenFunc *)sym)(curDevInfo);
141
}
142
if (ret == JDGA_SUCCESS) {
143
curDevInfo->visidName = strdup(visid.name);
144
return curDevInfo;
145
}
146
dlclose(handle);
147
}
148
}
149
return NULL;
150
}
151
static int
152
mmap_dgaDev(SolarisDgaLibInfo *libInfo, Dga_drawable dgadraw)
153
{
154
155
if (!libInfo->devInfo) {
156
libInfo->devInfo = getDevInfo(dgadraw);
157
if (!libInfo->devInfo) {
158
return JDGA_FAILED;
159
}
160
}
161
return (*libInfo->devInfo->function->winopen)(&(libInfo->winInfo));
162
}
163
164
static void
165
unmap_dgaDev(SolarisDgaLibInfo *pDevInfo)
166
{
167
DEBUG_PRINT(("winclose() called\n"));
168
(*pDevInfo->devInfo->function->winclose)(&(pDevInfo->winInfo));
169
}
170
171
static jboolean
172
Solaris_DGA_Available(Display *display)
173
{
174
Window root;
175
int screen;
176
Dga_drawable dgaDrawable;
177
SolarisJDgaDevInfo * devinfo;
178
179
/* return true if any screen supports DGA and we
180
have a library for this type of framebuffer */
181
for (screen = 0; screen < XScreenCount(display); screen++) {
182
root = RootWindow(display, screen);
183
184
dgaDrawable = XDgaGrabDrawable(display, root);
185
if (dgaDrawable != 0) {
186
devinfo = getDevInfo(dgaDrawable);
187
XDgaUnGrabDrawable(dgaDrawable);
188
if (devinfo != NULL) {
189
return JNI_TRUE;
190
}
191
}
192
}
193
return JNI_FALSE;
194
}
195
196
static JDgaLibInitFunc Solaris_DGA_LibInit;
197
static JDgaGetLockFunc Solaris_DGA_GetLock;
198
static JDgaReleaseLockFunc Solaris_DGA_ReleaseLock;
199
static JDgaXRequestSentFunc Solaris_DGA_XRequestSent;
200
static JDgaLibDisposeFunc Solaris_DGA_LibDispose;
201
static int firstInitDone = 0;
202
203
#pragma weak JDgaLibInit = Solaris_DGA_LibInit
204
205
static JDgaStatus
206
Solaris_DGA_LibInit(JNIEnv *env, JDgaLibInfo *ppInfo)
207
{
208
/* Note: DGA_INIT can be called multiple times according to docs */
209
DEBUG_PRINT(("DGA_INIT called\n"));
210
DGA_INIT();
211
212
if (!Solaris_DGA_Available(ppInfo->display)) {
213
return JDGA_FAILED;
214
}
215
Solaris_DGA_XineramaInit(ppInfo->display);
216
217
ppInfo->pGetLock = Solaris_DGA_GetLock;
218
ppInfo->pReleaseLock = Solaris_DGA_ReleaseLock;
219
ppInfo->pXRequestSent = Solaris_DGA_XRequestSent;
220
ppInfo->pLibDispose = Solaris_DGA_LibDispose;
221
222
return JDGA_SUCCESS;
223
}
224
225
static JDgaStatus
226
Solaris_DGA_GetLock(JNIEnv *env, Display *display, void **dgaDev,
227
Drawable drawable, JDgaSurfaceInfo *pSurface,
228
jint lox, jint loy, jint hix, jint hiy)
229
{
230
SolarisDgaLibInfo *pDevInfo;
231
SolarisDgaLibInfo *pCachedInfo = cachedInfo;
232
int vis;
233
int dlox, dloy, dhix, dhiy;
234
int i;
235
int type, site;
236
unsigned long k;
237
Drawable prev_virtual_drawable = 0;
238
Dga_drawable dgaDrawable;
239
240
if (*dgaDev) {
241
if (((SolarisDgaLibInfo *)(*dgaDev))->drawable != drawable) {
242
*dgaDev = 0;
243
}
244
}
245
246
if (*dgaDev == 0) {
247
pCachedInfo = cachedInfo;
248
for (i = 0 ; (i < MAX_CACHED_INFO) && (pCachedInfo->drawable) ;
249
i++, pCachedInfo++) {
250
if (pCachedInfo->drawable == drawable) {
251
*dgaDev = pCachedInfo;
252
break;
253
}
254
}
255
if (*dgaDev == 0) {
256
if (i < MAX_CACHED_INFO) { /* slot can be used for new info */
257
*dgaDev = pCachedInfo;
258
} else {
259
pCachedInfo = cachedInfo;
260
/* find the least used slot but does not handle an overflow of
261
the counter */
262
for (i = 0, k = 0xffffffff; i < MAX_CACHED_INFO ;
263
i++, pCachedInfo++) {
264
if (k > pCachedInfo->count) {
265
k = pCachedInfo->count;
266
*dgaDev = pCachedInfo;
267
}
268
pCachedInfo->count = 0; /* reset all counters */
269
}
270
pCachedInfo = *dgaDev;
271
if (pCachedInfo->winInfo.dgaDraw != 0) {
272
XDgaUnGrabDrawable(pCachedInfo->winInfo.dgaDraw);
273
}
274
pCachedInfo->winInfo.dgaDraw = 0;
275
/* the slot might be used for another device */
276
pCachedInfo->devInfo = 0;
277
}
278
}
279
}
280
281
pDevInfo = *dgaDev;
282
pDevInfo->drawable = drawable;
283
284
prev_virtual_drawable = pDevInfo->virtual_drawable;
285
pDevInfo->virtual_drawable = GetVirtualDrawable(display, drawable);
286
if (pDevInfo->virtual_drawable == NULL) {
287
/* this usually means that the drawable is spanned across
288
screens in xinerama mode - we can't handle this for now */
289
return JDGA_FAILED;
290
} else {
291
/* check if the drawable has been moved to another screen
292
since last time */
293
if (pDevInfo->winInfo.dgaDraw != 0 &&
294
pDevInfo->virtual_drawable != prev_virtual_drawable) {
295
XDgaUnGrabDrawable(pDevInfo->winInfo.dgaDraw);
296
pDevInfo->winInfo.dgaDraw = 0;
297
}
298
}
299
300
pDevInfo->count++;
301
302
if (pDevInfo->winInfo.dgaDraw == 0) {
303
pDevInfo->winInfo.dgaDraw = XDgaGrabDrawable(display, pDevInfo->virtual_drawable);
304
if (pDevInfo->winInfo.dgaDraw == 0) {
305
DEBUG_PRINT(("DgaGrabDrawable failed for 0x%08x\n", drawable));
306
return JDGA_UNAVAILABLE;
307
}
308
type = dga_draw_type(pDevInfo->winInfo.dgaDraw);
309
if (type != DGA_DRAW_PIXMAP &&
310
mmap_dgaDev(pDevInfo, pDevInfo->winInfo.dgaDraw) != JDGA_SUCCESS) {
311
DEBUG_PRINT(("memory map failed for 0x%08x (depth = %d)\n",
312
drawable, dga_draw_depth(pDevInfo->winInfo.dgaDraw)));
313
XDgaUnGrabDrawable(pDevInfo->winInfo.dgaDraw);
314
pDevInfo->winInfo.dgaDraw = 0;
315
return JDGA_UNAVAILABLE;
316
}
317
} else {
318
type = dga_draw_type(pDevInfo->winInfo.dgaDraw);
319
}
320
321
if (needsSync) {
322
XSync(display, False);
323
needsSync = JNI_FALSE;
324
}
325
326
dgaDrawable = pDevInfo->winInfo.dgaDraw;
327
328
DGA_DRAW_LOCK(dgaDrawable, -1);
329
330
site = dga_draw_site(dgaDrawable);
331
if (type == DGA_DRAW_PIXMAP) {
332
if (site == DGA_SITE_SYSTEM) {
333
pDevInfo->winInfo.mapDepth = dga_draw_depth(dgaDrawable);
334
pDevInfo->winInfo.mapAddr = dga_draw_address(dgaDrawable);
335
dga_draw_bbox(dgaDrawable, &dlox, &dloy, &dhix, &dhiy);
336
pDevInfo->winInfo.mapWidth = dhix;
337
pDevInfo->winInfo.mapHeight = dhiy;
338
if (pDevInfo->winInfo.mapDepth == 8) {
339
pDevInfo->winInfo.mapLineStride = dga_draw_linebytes(dgaDrawable);
340
pDevInfo->winInfo.mapPixelStride = 1;
341
} else {
342
pDevInfo->winInfo.mapLineStride = dga_draw_linebytes(dgaDrawable)/4;
343
pDevInfo->winInfo.mapPixelStride = 4;
344
}
345
} else {
346
XDgaUnGrabDrawable(dgaDrawable);
347
pDevInfo->winInfo.dgaDraw = 0;
348
return JDGA_UNAVAILABLE;
349
}
350
} else {
351
if (site == DGA_SITE_NULL) {
352
DEBUG_PRINT(("zombie drawable = 0x%08x\n", dgaDrawable));
353
DGA_DRAW_UNLOCK(dgaDrawable);
354
unmap_dgaDev(pDevInfo);
355
XDgaUnGrabDrawable(dgaDrawable);
356
pDevInfo->winInfo.dgaDraw = 0;
357
return JDGA_UNAVAILABLE;
358
}
359
dga_draw_bbox(dgaDrawable, &dlox, &dloy, &dhix, &dhiy);
360
}
361
362
/* get the screen address of the drawable */
363
dhix += dlox;
364
dhiy += dloy;
365
DEBUG_PRINT(("window at (%d, %d) => (%d, %d)\n", dlox, dloy, dhix, dhiy));
366
pSurface->window.lox = dlox;
367
pSurface->window.loy = dloy;
368
pSurface->window.hix = dhix;
369
pSurface->window.hiy = dhiy;
370
371
/* translate rendering coordinates relative to device bbox */
372
lox += dlox;
373
loy += dloy;
374
hix += dlox;
375
hiy += dloy;
376
DEBUG_PRINT(("render at (%d, %d) => (%d, %d)\n", lox, loy, hix, hiy));
377
378
vis = dga_draw_visibility(dgaDrawable);
379
switch (vis) {
380
case DGA_VIS_UNOBSCURED:
381
pSurface->visible.lox = max(dlox, lox);
382
pSurface->visible.loy = max(dloy, loy);
383
pSurface->visible.hix = min(dhix, hix);
384
pSurface->visible.hiy = min(dhiy, hiy);
385
DEBUG_PRINT(("unobscured vis at (%d, %d) => (%d, %d)\n",
386
pSurface->visible.lox,
387
pSurface->visible.loy,
388
pSurface->visible.hix,
389
pSurface->visible.hiy));
390
break;
391
case DGA_VIS_PARTIALLY_OBSCURED: {
392
/*
393
* fix for #4305271
394
* the dga_draw_clipinfo call returns the clipping bounds
395
* in short ints, but use only full size ints for all comparisons.
396
*/
397
short *ptr;
398
int x0, y0, x1, y1;
399
int cliplox, cliploy, cliphix, cliphiy;
400
401
/*
402
* iterate to find out whether the clipped blit draws to a
403
* single clipping rectangle
404
*/
405
cliplox = cliphix = lox;
406
cliploy = cliphiy = loy;
407
ptr = dga_draw_clipinfo(dgaDrawable);
408
while (*ptr != DGA_Y_EOL) {
409
y0 = *ptr++;
410
y1 = *ptr++;
411
DEBUG_PRINT(("DGA y range loy=%d hiy=%d\n", y0, y1));
412
if (y0 < loy) {
413
y0 = loy;
414
}
415
if (y1 > hiy) {
416
y1 = hiy;
417
}
418
while (*ptr != DGA_X_EOL) {
419
x0 = *ptr++;
420
x1 = *ptr++;
421
DEBUG_PRINT((" DGA x range lox=%d hix=%d\n", x0, x1));
422
if (x0 < lox) {
423
x0 = lox;
424
}
425
if (x1 > hix) {
426
x1 = hix;
427
}
428
if (x0 < x1 && y0 < y1) {
429
if (cliploy == cliphiy) {
430
/* First rectangle intersection */
431
cliplox = x0;
432
cliploy = y0;
433
cliphix = x1;
434
cliphiy = y1;
435
} else {
436
/* Can we merge this rect with previous? */
437
if (cliplox == x0 && cliphix == x1 &&
438
cliploy <= y1 && cliphiy >= y0)
439
{
440
/* X ranges match, Y ranges touch */
441
/* => absorb the Y ranges together */
442
cliploy = min(cliploy, y0);
443
cliphiy = max(cliphiy, y1);
444
} else if (cliploy == y0 && cliphiy == y1 &&
445
cliplox <= x1 && cliphix >= x0)
446
{
447
/* Y ranges match, X ranges touch */
448
/* => Absorb the X ranges together */
449
cliplox = min(cliplox, x0);
450
cliphix = max(cliphix, x1);
451
} else {
452
/* Assertion: any other combination */
453
/* means non-rectangular intersect */
454
DGA_DRAW_UNLOCK(dgaDrawable);
455
return JDGA_FAILED;
456
}
457
}
458
}
459
}
460
ptr++; /* advance past DGA_X_EOL */
461
}
462
DEBUG_PRINT(("DGA drawable fits\n"));
463
pSurface->visible.lox = cliplox;
464
pSurface->visible.loy = cliploy;
465
pSurface->visible.hix = cliphix;
466
pSurface->visible.hiy = cliphiy;
467
break;
468
}
469
case DGA_VIS_FULLY_OBSCURED:
470
pSurface->visible.lox =
471
pSurface->visible.hix = lox;
472
pSurface->visible.loy =
473
pSurface->visible.hiy = loy;
474
DEBUG_PRINT(("fully obscured vis\n"));
475
break;
476
default:
477
DEBUG_PRINT(("unknown visibility = %d!\n", vis));
478
DGA_DRAW_UNLOCK(dgaDrawable);
479
return JDGA_FAILED;
480
}
481
482
pSurface->basePtr = pDevInfo->winInfo.mapAddr;
483
pSurface->surfaceScan = pDevInfo->winInfo.mapLineStride;
484
pSurface->surfaceWidth = pDevInfo->winInfo.mapWidth;
485
pSurface->surfaceHeight = pDevInfo->winInfo.mapHeight;
486
pSurface->surfaceDepth = pDevInfo->winInfo.mapDepth;
487
488
return JDGA_SUCCESS;
489
}
490
491
static JDgaStatus
492
Solaris_DGA_ReleaseLock(JNIEnv *env, void *dgaDev, Drawable drawable)
493
{
494
SolarisDgaLibInfo *pDevInfo = (SolarisDgaLibInfo *) dgaDev;
495
496
if (pDevInfo != 0 && pDevInfo->drawable == drawable &&
497
pDevInfo->winInfo.dgaDraw != 0) {
498
DGA_DRAW_UNLOCK(pDevInfo->winInfo.dgaDraw);
499
}
500
return JDGA_SUCCESS;
501
}
502
503
static void
504
Solaris_DGA_XRequestSent(JNIEnv *env, void *dgaDev, Drawable drawable)
505
{
506
needsSync = JNI_TRUE;
507
}
508
509
static void
510
Solaris_DGA_LibDispose(JNIEnv *env)
511
{
512
SolarisDgaLibInfo *pCachedInfo = cachedInfo;
513
SolarisJDgaDevInfo *curDevInfo = devicesInfo;
514
int i;
515
516
for (i = 0 ; (i < MAX_CACHED_INFO) && (pCachedInfo->drawable) ;
517
i++, pCachedInfo++) {
518
if (pCachedInfo->winInfo.dgaDraw != 0) {
519
if (dga_draw_type(pCachedInfo->winInfo.dgaDraw) == DGA_DRAW_WINDOW &&
520
pCachedInfo->winInfo.mapDepth != 0) {
521
unmap_dgaDev(pCachedInfo);
522
}
523
XDgaUnGrabDrawable(pCachedInfo->winInfo.dgaDraw);
524
pCachedInfo->winInfo.dgaDraw = 0;
525
}
526
}
527
for (i = 0; (i < MAX_FB_TYPES) && (curDevInfo->visidName);
528
i++, curDevInfo++) {
529
curDevInfo->function->devclose(curDevInfo);
530
free(curDevInfo->visidName);
531
}
532
}
533
#endif
534
535