Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m
41159 views
1
/*
2
* Copyright (c) 2011, 2019, 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
#import <stdlib.h>
27
28
#import "sun_java2d_opengl_CGLSurfaceData.h"
29
30
#import "JNIUtilities.h"
31
#import "OGLRenderQueue.h"
32
#import "CGLGraphicsConfig.h"
33
#import "CGLSurfaceData.h"
34
#import "ThreadUtilities.h"
35
36
/* JDK's glext.h is already included and will prevent the Apple glext.h
37
* being included, so define the externs directly
38
*/
39
extern void glBindFramebufferEXT(GLenum target, GLuint framebuffer);
40
extern CGLError CGLTexImageIOSurface2D(
41
CGLContextObj ctx, GLenum target, GLenum internal_format,
42
GLsizei width, GLsizei height, GLenum format, GLenum type,
43
IOSurfaceRef ioSurface, GLuint plane);
44
45
/**
46
* The methods in this file implement the native windowing system specific
47
* layer (CGL) for the OpenGL-based Java 2D pipeline.
48
*/
49
50
#pragma mark -
51
#pragma mark "--- Mac OS X specific methods for GL pipeline ---"
52
53
// TODO: hack that's called from OGLRenderQueue to test out unlockFocus behavior
54
#if 0
55
void
56
OGLSD_UnlockFocus(OGLContext *oglc, OGLSDOps *dstOps)
57
{
58
CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
59
CGLSDOps *cglsdo = (CGLSDOps *)dstOps->privOps;
60
fprintf(stderr, "about to unlock focus: %p %p\n",
61
cglsdo->peerData, ctxinfo->context);
62
63
NSOpenGLView *nsView = cglsdo->peerData;
64
if (nsView != NULL) {
65
JNI_COCOA_ENTER(env);
66
[nsView unlockFocus];
67
JNI_COCOA_EXIT(env);
68
}
69
}
70
#endif
71
72
/**
73
* Makes the given context current to its associated "scratch" surface. If
74
* the operation is successful, this method will return JNI_TRUE; otherwise,
75
* returns JNI_FALSE.
76
*/
77
static jboolean
78
CGLSD_MakeCurrentToScratch(JNIEnv *env, OGLContext *oglc)
79
{
80
J2dTraceLn(J2D_TRACE_INFO, "CGLSD_MakeCurrentToScratch");
81
82
if (oglc == NULL) {
83
J2dRlsTraceLn(J2D_TRACE_ERROR,
84
"CGLSD_MakeCurrentToScratch: context is null");
85
return JNI_FALSE;
86
}
87
88
JNI_COCOA_ENTER(env);
89
90
CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
91
#if USE_NSVIEW_FOR_SCRATCH
92
[ctxinfo->context makeCurrentContext];
93
#else
94
[ctxinfo->context clearDrawable];
95
[ctxinfo->context makeCurrentContext];
96
[ctxinfo->context setPixelBuffer: ctxinfo->scratchSurface
97
cubeMapFace: 0
98
mipMapLevel: 0
99
currentVirtualScreen: [ctxinfo->context currentVirtualScreen]];
100
#endif
101
102
JNI_COCOA_EXIT(env);
103
104
return JNI_TRUE;
105
}
106
107
/**
108
* This function disposes of any native windowing system resources associated
109
* with this surface.
110
*/
111
void
112
OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo)
113
{
114
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface");
115
116
JNI_COCOA_ENTER(env);
117
118
CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps;
119
if (oglsdo->drawableType == OGLSD_WINDOW) {
120
// detach the NSView from the NSOpenGLContext
121
CGLGraphicsConfigInfo *cglInfo = cglsdo->configInfo;
122
OGLContext *oglc = cglInfo->context;
123
CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
124
[ctxinfo->context clearDrawable];
125
}
126
127
oglsdo->drawableType = OGLSD_UNDEFINED;
128
129
JNI_COCOA_EXIT(env);
130
}
131
132
/**
133
* Makes the given GraphicsConfig's context current to its associated
134
* "scratch" surface. If there is a problem making the context current,
135
* this method will return NULL; otherwise, returns a pointer to the
136
* OGLContext that is associated with the given GraphicsConfig.
137
*/
138
OGLContext *
139
OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo)
140
{
141
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SetScratchContext");
142
143
CGLGraphicsConfigInfo *cglInfo = (CGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
144
if (cglInfo == NULL) {
145
J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_SetScratchContext: cgl config info is null");
146
return NULL;
147
}
148
149
OGLContext *oglc = cglInfo->context;
150
if (oglc == NULL) {
151
J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_SetScratchContext: ogl context is null");
152
return NULL;
153
}
154
155
CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
156
157
JNI_COCOA_ENTER(env);
158
159
// avoid changing the context's target view whenever possible, since
160
// calling setView causes flickering; as long as our context is current
161
// to some view, it's not necessary to switch to the scratch surface
162
if ([ctxinfo->context view] == nil) {
163
// it seems to be necessary to explicitly flush between context changes
164
OGLContext *currentContext = OGLRenderQueue_GetCurrentContext();
165
if (currentContext != NULL) {
166
j2d_glFlush();
167
}
168
169
if (!CGLSD_MakeCurrentToScratch(env, oglc)) {
170
return NULL;
171
}
172
// make sure our context is current
173
} else if ([NSOpenGLContext currentContext] != ctxinfo->context) {
174
[ctxinfo->context makeCurrentContext];
175
}
176
177
if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
178
// the GL_EXT_framebuffer_object extension is present, so this call
179
// will ensure that we are bound to the scratch surface (and not
180
// some other framebuffer object)
181
j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
182
}
183
184
JNI_COCOA_EXIT(env);
185
186
return oglc;
187
}
188
189
/**
190
* Makes a context current to the given source and destination
191
* surfaces. If there is a problem making the context current, this method
192
* will return NULL; otherwise, returns a pointer to the OGLContext that is
193
* associated with the destination surface.
194
*/
195
OGLContext *
196
OGLSD_MakeOGLContextCurrent(JNIEnv *env, OGLSDOps *srcOps, OGLSDOps *dstOps)
197
{
198
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_MakeOGLContextCurrent");
199
200
CGLSDOps *dstCGLOps = (CGLSDOps *)dstOps->privOps;
201
202
J2dTraceLn4(J2D_TRACE_VERBOSE, " src: %d %p dst: %d %p", srcOps->drawableType, srcOps, dstOps->drawableType, dstOps);
203
204
OGLContext *oglc = dstCGLOps->configInfo->context;
205
if (oglc == NULL) {
206
J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_MakeOGLContextCurrent: context is null");
207
return NULL;
208
}
209
210
CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
211
212
// it seems to be necessary to explicitly flush between context changes
213
OGLContext *currentContext = OGLRenderQueue_GetCurrentContext();
214
if (currentContext != NULL) {
215
j2d_glFlush();
216
}
217
218
if (dstOps->drawableType == OGLSD_FBOBJECT) {
219
// first make sure we have a current context (if the context isn't
220
// already current to some drawable, we will make it current to
221
// its scratch surface)
222
if (oglc != currentContext) {
223
if (!CGLSD_MakeCurrentToScratch(env, oglc)) {
224
return NULL;
225
}
226
}
227
228
// now bind to the fbobject associated with the destination surface;
229
// this means that all rendering will go into the fbobject destination
230
// (note that we unbind the currently bound texture first; this is
231
// recommended procedure when binding an fbobject)
232
j2d_glBindTexture(GL_TEXTURE_2D, 0);
233
j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID);
234
235
return oglc;
236
}
237
238
JNI_COCOA_ENTER(env);
239
240
CGLSDOps *cglsdo = (CGLSDOps *)dstOps->privOps;
241
NSView *nsView = (NSView *)cglsdo->peerData;
242
243
if ([ctxinfo->context view] != nsView) {
244
[ctxinfo->context makeCurrentContext];
245
[ctxinfo->context setView: nsView];
246
}
247
248
if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
249
// the GL_EXT_framebuffer_object extension is present, so we
250
// must bind to the default (windowing system provided)
251
// framebuffer
252
j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
253
}
254
255
JNI_COCOA_EXIT(env);
256
257
return oglc;
258
}
259
260
/**
261
* This function initializes a native window surface and caches the window
262
* bounds in the given OGLSDOps. Returns JNI_TRUE if the operation was
263
* successful; JNI_FALSE otherwise.
264
*/
265
jboolean
266
OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo)
267
{
268
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow");
269
270
if (oglsdo == NULL) {
271
J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: ops are null");
272
return JNI_FALSE;
273
}
274
275
CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps;
276
if (cglsdo == NULL) {
277
J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: cgl ops are null");
278
return JNI_FALSE;
279
}
280
281
AWTView *v = cglsdo->peerData;
282
if (v == NULL) {
283
J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: view is invalid");
284
return JNI_FALSE;
285
}
286
287
JNI_COCOA_ENTER(env);
288
NSRect surfaceBounds = [v bounds];
289
oglsdo->drawableType = OGLSD_WINDOW;
290
oglsdo->isOpaque = JNI_TRUE;
291
oglsdo->width = surfaceBounds.size.width;
292
oglsdo->height = surfaceBounds.size.height;
293
JNI_COCOA_EXIT(env);
294
295
J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", oglsdo->width, oglsdo->height);
296
297
return JNI_TRUE;
298
}
299
300
void
301
OGLSD_SwapBuffers(JNIEnv *env, jlong pPeerData)
302
{
303
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers");
304
305
JNI_COCOA_ENTER(env);
306
[[NSOpenGLContext currentContext] flushBuffer];
307
JNI_COCOA_EXIT(env);
308
}
309
310
void
311
OGLSD_Flush(JNIEnv *env)
312
{
313
OGLSDOps *dstOps = OGLRenderQueue_GetCurrentDestination();
314
if (dstOps != NULL) {
315
CGLSDOps *dstCGLOps = (CGLSDOps *)dstOps->privOps;
316
CGLLayer *layer = (CGLLayer*)dstCGLOps->layer;
317
if (layer != NULL) {
318
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
319
AWT_ASSERT_APPKIT_THREAD;
320
[layer setNeedsDisplay];
321
}];
322
}
323
}
324
}
325
326
#pragma mark -
327
#pragma mark "--- CGLSurfaceData methods ---"
328
329
extern LockFunc OGLSD_Lock;
330
extern GetRasInfoFunc OGLSD_GetRasInfo;
331
extern UnlockFunc OGLSD_Unlock;
332
extern DisposeFunc OGLSD_Dispose;
333
334
JNIEXPORT void JNICALL
335
Java_sun_java2d_opengl_CGLSurfaceData_initOps
336
(JNIEnv *env, jobject cglsd, jobject gc,
337
jlong pConfigInfo, jlong pPeerData, jlong layerPtr,
338
jint xoff, jint yoff, jboolean isOpaque)
339
{
340
J2dTraceLn(J2D_TRACE_INFO, "CGLSurfaceData_initOps");
341
J2dTraceLn1(J2D_TRACE_INFO, " pPeerData=%p", jlong_to_ptr(pPeerData));
342
J2dTraceLn2(J2D_TRACE_INFO, " xoff=%d, yoff=%d", (int)xoff, (int)yoff);
343
344
gc = (*env)->NewGlobalRef(env, gc);
345
if (gc == NULL) {
346
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
347
return;
348
}
349
350
OGLSDOps *oglsdo = (OGLSDOps *)
351
SurfaceData_InitOps(env, cglsd, sizeof(OGLSDOps));
352
if (oglsdo == NULL) {
353
(*env)->DeleteGlobalRef(env, gc);
354
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
355
return;
356
}
357
// later the graphicsConfig will be used for deallocation of oglsdo
358
oglsdo->graphicsConfig = gc;
359
360
CGLSDOps *cglsdo = (CGLSDOps *)malloc(sizeof(CGLSDOps));
361
if (cglsdo == NULL) {
362
JNU_ThrowOutOfMemoryError(env, "creating native cgl ops");
363
return;
364
}
365
366
oglsdo->privOps = cglsdo;
367
368
oglsdo->sdOps.Lock = OGLSD_Lock;
369
oglsdo->sdOps.GetRasInfo = OGLSD_GetRasInfo;
370
oglsdo->sdOps.Unlock = OGLSD_Unlock;
371
oglsdo->sdOps.Dispose = OGLSD_Dispose;
372
373
oglsdo->drawableType = OGLSD_UNDEFINED;
374
oglsdo->activeBuffer = GL_FRONT;
375
oglsdo->needsInit = JNI_TRUE;
376
oglsdo->xOffset = xoff;
377
oglsdo->yOffset = yoff;
378
oglsdo->isOpaque = isOpaque;
379
380
cglsdo->peerData = (AWTView *)jlong_to_ptr(pPeerData);
381
cglsdo->layer = (CGLLayer *)jlong_to_ptr(layerPtr);
382
cglsdo->configInfo = (CGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
383
384
if (cglsdo->configInfo == NULL) {
385
free(cglsdo);
386
JNU_ThrowNullPointerException(env, "Config info is null in initOps");
387
}
388
}
389
390
JNIEXPORT void JNICALL
391
Java_sun_java2d_opengl_CGLSurfaceData_clearWindow
392
(JNIEnv *env, jobject cglsd)
393
{
394
J2dTraceLn(J2D_TRACE_INFO, "CGLSurfaceData_clearWindow");
395
396
OGLSDOps *oglsdo = (OGLSDOps*) SurfaceData_GetOps(env, cglsd);
397
CGLSDOps *cglsdo = (CGLSDOps*) oglsdo->privOps;
398
399
cglsdo->peerData = NULL;
400
cglsdo->layer = NULL;
401
}
402
403