Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/windows/native/libawt/java2d/opengl/WGLSurfaceData.c
41159 views
1
/*
2
* Copyright (c) 2004, 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
#include <stdlib.h>
27
28
#include "sun_java2d_opengl_WGLSurfaceData.h"
29
30
#include "jni.h"
31
#include "jlong.h"
32
#include "jni_util.h"
33
#include "sizecalc.h"
34
#include "OGLRenderQueue.h"
35
#include "WGLGraphicsConfig.h"
36
#include "WGLSurfaceData.h"
37
38
/**
39
* The methods in this file implement the native windowing system specific
40
* layer (WGL) for the OpenGL-based Java 2D pipeline.
41
*/
42
43
extern LockFunc OGLSD_Lock;
44
extern GetRasInfoFunc OGLSD_GetRasInfo;
45
extern UnlockFunc OGLSD_Unlock;
46
extern DisposeFunc OGLSD_Dispose;
47
48
extern OGLPixelFormat PixelFormats[];
49
extern void AwtWindow_UpdateWindow(JNIEnv *env, jobject peer,
50
jint w, jint h, HBITMAP hBitmap);
51
extern HBITMAP BitmapUtil_CreateBitmapFromARGBPre(int width, int height,
52
int srcStride,
53
int* imageData);
54
extern void AwtComponent_GetInsets(JNIEnv *env, jobject peer, RECT *insets);
55
56
extern void
57
OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, jint w, jint h);
58
59
JNIEXPORT void JNICALL
60
Java_sun_java2d_opengl_WGLSurfaceData_initOps(JNIEnv *env, jobject wglsd,
61
jobject gc, jlong pConfigInfo,
62
jobject peer, jlong hwnd)
63
{
64
gc = (*env)->NewGlobalRef(env, gc);
65
if (gc == NULL) {
66
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
67
return;
68
}
69
70
OGLSDOps *oglsdo = (OGLSDOps *)SurfaceData_InitOps(env, wglsd,
71
sizeof(OGLSDOps));
72
if (oglsdo == NULL) {
73
(*env)->DeleteGlobalRef(env, gc);
74
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
75
return;
76
}
77
// later the graphicsConfig will be used for deallocation of oglsdo
78
oglsdo->graphicsConfig = gc;
79
80
WGLSDOps *wglsdo = (WGLSDOps *)malloc(sizeof(WGLSDOps));
81
82
J2dTraceLn(J2D_TRACE_INFO, "WGLSurfaceData_initOps");
83
84
if (wglsdo == NULL) {
85
JNU_ThrowOutOfMemoryError(env, "creating native wgl ops");
86
return;
87
}
88
if (oglsdo == NULL) {
89
free(wglsdo);
90
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
91
return;
92
}
93
94
oglsdo->privOps = wglsdo;
95
96
oglsdo->sdOps.Lock = OGLSD_Lock;
97
oglsdo->sdOps.GetRasInfo = OGLSD_GetRasInfo;
98
oglsdo->sdOps.Unlock = OGLSD_Unlock;
99
oglsdo->sdOps.Dispose = OGLSD_Dispose;
100
101
oglsdo->drawableType = OGLSD_UNDEFINED;
102
oglsdo->activeBuffer = GL_FRONT;
103
oglsdo->needsInit = JNI_TRUE;
104
if (peer != NULL) {
105
RECT insets;
106
AwtComponent_GetInsets(env, peer, &insets);
107
oglsdo->xOffset = -insets.left;
108
oglsdo->yOffset = -insets.bottom;
109
} else {
110
oglsdo->xOffset = 0;
111
oglsdo->yOffset = 0;
112
}
113
114
wglsdo->window = (HWND)jlong_to_ptr(hwnd);
115
wglsdo->configInfo = (WGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
116
if (wglsdo->configInfo == NULL) {
117
free(wglsdo);
118
JNU_ThrowNullPointerException(env, "Config info is null in initOps");
119
}
120
}
121
122
/**
123
* This function disposes of any native windowing system resources associated
124
* with this surface.
125
*/
126
void
127
OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo)
128
{
129
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface");
130
// Window is free'd later by AWT code...
131
}
132
133
/**
134
* Makes the given context current to its associated "scratch" surface. If
135
* the operation is successful, this method will return JNI_TRUE; otherwise,
136
* returns JNI_FALSE.
137
*/
138
static jboolean
139
WGLSD_MakeCurrentToScratch(JNIEnv *env, OGLContext *oglc)
140
{
141
WGLCtxInfo *ctxInfo;
142
143
J2dTraceLn(J2D_TRACE_INFO, "WGLSD_MakeCurrentToScratch");
144
145
if (oglc == NULL) {
146
J2dRlsTraceLn(J2D_TRACE_ERROR,
147
"WGLSD_MakeCurrentToScratch: context is null");
148
return JNI_FALSE;
149
}
150
151
ctxInfo = (WGLCtxInfo *)oglc->ctxInfo;
152
if (!j2d_wglMakeCurrent(ctxInfo->scratchSurfaceDC, ctxInfo->context)) {
153
J2dRlsTraceLn(J2D_TRACE_ERROR,
154
"WGLSD_MakeCurrentToScratch: could not make current");
155
return JNI_FALSE;
156
}
157
158
return JNI_TRUE;
159
}
160
161
/**
162
* Makes the given GraphicsConfig's context current to its associated
163
* "scratch" surface. If there is a problem making the context current,
164
* this method will return NULL; otherwise, returns a pointer to the
165
* OGLContext that is associated with the given GraphicsConfig.
166
*/
167
OGLContext *
168
OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo)
169
{
170
WGLGraphicsConfigInfo *wglInfo =
171
(WGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
172
OGLContext *oglc;
173
174
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SetScratchContext");
175
176
if (wglInfo == NULL) {
177
J2dRlsTraceLn(J2D_TRACE_ERROR,
178
"OGLSD_SetScratchContext: wgl config info is null");
179
return NULL;
180
}
181
182
oglc = wglInfo->context;
183
if (!WGLSD_MakeCurrentToScratch(env, oglc)) {
184
return NULL;
185
}
186
187
if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
188
// the GL_EXT_framebuffer_object extension is present, so this call
189
// will ensure that we are bound to the scratch pbuffer (and not
190
// some other framebuffer object)
191
j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
192
}
193
194
return oglc;
195
}
196
197
/**
198
* Makes a context current to the given source and destination
199
* surfaces. If there is a problem making the context current, this method
200
* will return NULL; otherwise, returns a pointer to the OGLContext that is
201
* associated with the destination surface.
202
*/
203
OGLContext *
204
OGLSD_MakeOGLContextCurrent(JNIEnv *env, OGLSDOps *srcOps, OGLSDOps *dstOps)
205
{
206
WGLSDOps *srcWGLOps = (WGLSDOps *)srcOps->privOps;
207
WGLSDOps *dstWGLOps = (WGLSDOps *)dstOps->privOps;
208
OGLContext *oglc;
209
WGLCtxInfo *ctxinfo;
210
HDC srcHDC, dstHDC;
211
BOOL success;
212
213
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_MakeOGLContextCurrent");
214
215
J2dTraceLn4(J2D_TRACE_VERBOSE, " src: %d %p dst: %d %p",
216
srcOps->drawableType, srcOps,
217
dstOps->drawableType, dstOps);
218
219
oglc = dstWGLOps->configInfo->context;
220
if (oglc == NULL) {
221
J2dRlsTraceLn(J2D_TRACE_ERROR,
222
"OGLSD_MakeOGLContextCurrent: context is null");
223
return NULL;
224
}
225
226
if (dstOps->drawableType == OGLSD_FBOBJECT) {
227
OGLContext *currentContext = OGLRenderQueue_GetCurrentContext();
228
229
// first make sure we have a current context (if the context isn't
230
// already current to some drawable, we will make it current to
231
// its scratch surface)
232
if (oglc != currentContext) {
233
if (!WGLSD_MakeCurrentToScratch(env, oglc)) {
234
return NULL;
235
}
236
}
237
238
// now bind to the fbobject associated with the destination surface;
239
// this means that all rendering will go into the fbobject destination
240
// (note that we unbind the currently bound texture first; this is
241
// recommended procedure when binding an fbobject)
242
j2d_glBindTexture(dstOps->textureTarget, 0);
243
j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID);
244
245
return oglc;
246
}
247
248
ctxinfo = (WGLCtxInfo *)oglc->ctxInfo;
249
250
// get the hdc for the destination surface
251
dstHDC = GetDC(dstWGLOps->window);
252
253
// get the hdc for the source surface
254
// the source will always be equal to the destination in this case
255
srcHDC = dstHDC;
256
257
// REMIND: in theory we should be able to use wglMakeContextCurrentARB()
258
// even when the src/dst surfaces are the same, but this causes problems
259
// on ATI's drivers (see 6525997); for now we will only use it when the
260
// surfaces are different, otherwise we will use the old
261
// wglMakeCurrent() approach...
262
if (srcHDC != dstHDC) {
263
// use WGL_ARB_make_current_read extension to make context current
264
success =
265
j2d_wglMakeContextCurrentARB(dstHDC, srcHDC, ctxinfo->context);
266
} else {
267
// use the old approach for making current to the destination
268
success = j2d_wglMakeCurrent(dstHDC, ctxinfo->context);
269
}
270
if (!success) {
271
J2dRlsTraceLn(J2D_TRACE_ERROR,
272
"OGLSD_MakeOGLContextCurrent: could not make current");
273
ReleaseDC(dstWGLOps->window, dstHDC);
274
return NULL;
275
}
276
277
if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
278
// the GL_EXT_framebuffer_object extension is present, so we
279
// must bind to the default (windowing system provided)
280
// framebuffer
281
j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
282
}
283
284
ReleaseDC(dstWGLOps->window, dstHDC);
285
286
return oglc;
287
}
288
289
/**
290
* This function initializes a native window surface and caches the window
291
* bounds in the given OGLSDOps. Returns JNI_TRUE if the operation was
292
* successful; JNI_FALSE otherwise.
293
*/
294
jboolean
295
OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo)
296
{
297
PIXELFORMATDESCRIPTOR pfd;
298
WGLSDOps *wglsdo;
299
WGLGraphicsConfigInfo *wglInfo;
300
HWND window;
301
RECT wbounds;
302
HDC hdc;
303
304
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow");
305
306
if (oglsdo == NULL) {
307
J2dRlsTraceLn(J2D_TRACE_ERROR,
308
"OGLSD_InitOGLWindow: ops are null");
309
return JNI_FALSE;
310
}
311
312
wglsdo = (WGLSDOps *)oglsdo->privOps;
313
if (wglsdo == NULL) {
314
J2dRlsTraceLn(J2D_TRACE_ERROR,
315
"OGLSD_InitOGLWindow: wgl ops are null");
316
return JNI_FALSE;
317
}
318
319
wglInfo = wglsdo->configInfo;
320
if (wglInfo == NULL) {
321
J2dRlsTraceLn(J2D_TRACE_ERROR,
322
"OGLSD_InitOGLWindow: graphics config info is null");
323
return JNI_FALSE;
324
}
325
326
window = wglsdo->window;
327
if (!IsWindow(window)) {
328
J2dRlsTraceLn(J2D_TRACE_ERROR,
329
"OGLSD_InitOGLWindow: disposed component");
330
return JNI_FALSE;
331
}
332
333
GetWindowRect(window, &wbounds);
334
335
hdc = GetDC(window);
336
if (hdc == 0) {
337
J2dRlsTraceLn(J2D_TRACE_ERROR,
338
"OGLSD_InitOGLWindow: invalid hdc");
339
return JNI_FALSE;
340
}
341
342
if (!SetPixelFormat(hdc, wglInfo->pixfmt, &pfd)) {
343
J2dRlsTraceLn(J2D_TRACE_ERROR,
344
"OGLSD_InitOGLWindow: error setting pixel format");
345
ReleaseDC(window, hdc);
346
return JNI_FALSE;
347
}
348
349
ReleaseDC(window, hdc);
350
351
oglsdo->drawableType = OGLSD_WINDOW;
352
oglsdo->isOpaque = JNI_TRUE;
353
oglsdo->width = wbounds.right - wbounds.left;
354
oglsdo->height = wbounds.bottom - wbounds.top;
355
wglsdo->pbufferDC = 0;
356
357
J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d",
358
oglsdo->width, oglsdo->height);
359
360
return JNI_TRUE;
361
}
362
363
void
364
OGLSD_SwapBuffers(JNIEnv *env, jlong pPeerData)
365
{
366
HWND window;
367
HDC hdc;
368
369
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers");
370
371
window = AwtComponent_GetHWnd(env, pPeerData);
372
if (!IsWindow(window)) {
373
J2dRlsTraceLn(J2D_TRACE_ERROR,
374
"OGLSD_SwapBuffers: disposed component");
375
return;
376
}
377
378
hdc = GetDC(window);
379
if (hdc == 0) {
380
J2dRlsTraceLn(J2D_TRACE_ERROR,
381
"OGLSD_SwapBuffers: invalid hdc");
382
return;
383
}
384
385
if (!SwapBuffers(hdc)) {
386
J2dRlsTraceLn(J2D_TRACE_ERROR,
387
"OGLSD_SwapBuffers: error in SwapBuffers");
388
}
389
390
if (!ReleaseDC(window, hdc)) {
391
J2dRlsTraceLn(J2D_TRACE_ERROR,
392
"OGLSD_SwapBuffers: error while releasing dc");
393
}
394
}
395
396
// needed by Mac OS X port, no-op on other platforms
397
void
398
OGLSD_Flush(JNIEnv *env)
399
{
400
}
401
402
/*
403
* Class: sun_java2d_opengl_WGLSurfaceData
404
* Method: updateWindowAccelImpl
405
* Signature: (JJII)Z
406
*/
407
JNIEXPORT jboolean JNICALL
408
Java_sun_java2d_opengl_WGLSurfaceData_updateWindowAccelImpl
409
(JNIEnv *env, jclass clazz, jlong pData, jobject peer, jint w, jint h)
410
{
411
OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData);
412
OGLPixelFormat pf = PixelFormats[0/*PF_INT_ARGB_PRE*/];
413
HBITMAP hBitmap = NULL;
414
void *pDst;
415
jint srcx, srcy, dstx, dsty, width, height;
416
jint pixelStride = 4;
417
jint scanStride = pixelStride * w;
418
419
J2dTraceLn(J2D_TRACE_INFO, "WGLSurfaceData_updateWindowAccelImpl");
420
421
if (w <= 0 || h <= 0) {
422
return JNI_TRUE;
423
}
424
if (oglsdo == NULL) {
425
return JNI_FALSE;
426
}
427
RESET_PREVIOUS_OP();
428
429
width = w;
430
height = h;
431
srcx = srcy = dstx = dsty = 0;
432
433
pDst = SAFE_SIZE_ARRAY_ALLOC(malloc, height, scanStride);
434
if (pDst == NULL) {
435
return JNI_FALSE;
436
}
437
ZeroMemory(pDst, height * scanStride);
438
439
// the code below is mostly copied from OGLBlitLoops_SurfaceToSwBlit
440
441
j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, dstx);
442
j2d_glPixelStorei(GL_PACK_ROW_LENGTH, scanStride / pixelStride);
443
j2d_glPixelStorei(GL_PACK_ALIGNMENT, pf.alignment);
444
445
// this accounts for lower-left origin of the source region
446
srcx = oglsdo->xOffset + srcx;
447
srcy = oglsdo->yOffset + oglsdo->height - (srcy + 1);
448
// we must read one scanline at a time because there is no way
449
// to read starting at the top-left corner of the source region
450
while (height > 0) {
451
j2d_glPixelStorei(GL_PACK_SKIP_ROWS, dsty);
452
j2d_glReadPixels(srcx, srcy, width, 1,
453
pf.format, pf.type, pDst);
454
srcy--;
455
dsty++;
456
height--;
457
}
458
459
j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
460
j2d_glPixelStorei(GL_PACK_SKIP_ROWS, 0);
461
j2d_glPixelStorei(GL_PACK_ROW_LENGTH, 0);
462
j2d_glPixelStorei(GL_PACK_ALIGNMENT, 4);
463
464
// the pixels read from the surface are already premultiplied
465
hBitmap = BitmapUtil_CreateBitmapFromARGBPre(w, h, scanStride,
466
(int*)pDst);
467
free(pDst);
468
469
if (hBitmap == NULL) {
470
return JNI_FALSE;
471
}
472
473
AwtWindow_UpdateWindow(env, peer, w, h, hBitmap);
474
475
// hBitmap is released in UpdateWindow
476
477
return JNI_TRUE;
478
}
479
480