Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/java2d/opengl/WGLSurfaceData.c
32288 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
OGLSDOps *oglsdo;
65
WGLSDOps *wglsdo;
66
67
gc = (*env)->NewGlobalRef(env, gc);
68
if (gc == NULL) {
69
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
70
return;
71
}
72
73
oglsdo = (OGLSDOps *)SurfaceData_InitOps(env, wglsd,
74
sizeof(OGLSDOps));
75
if (oglsdo == NULL) {
76
(*env)->DeleteGlobalRef(env, gc);
77
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
78
return;
79
}
80
// later the graphicsConfig will be used for deallocation of oglsdo
81
oglsdo->graphicsConfig = gc;
82
83
wglsdo = (WGLSDOps *)malloc(sizeof(WGLSDOps));
84
85
J2dTraceLn(J2D_TRACE_INFO, "WGLSurfaceData_initOps");
86
87
if (wglsdo == NULL) {
88
JNU_ThrowOutOfMemoryError(env, "creating native wgl ops");
89
return;
90
}
91
if (oglsdo == NULL) {
92
free(wglsdo);
93
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
94
return;
95
}
96
97
oglsdo->privOps = wglsdo;
98
99
oglsdo->sdOps.Lock = OGLSD_Lock;
100
oglsdo->sdOps.GetRasInfo = OGLSD_GetRasInfo;
101
oglsdo->sdOps.Unlock = OGLSD_Unlock;
102
oglsdo->sdOps.Dispose = OGLSD_Dispose;
103
104
oglsdo->drawableType = OGLSD_UNDEFINED;
105
oglsdo->activeBuffer = GL_FRONT;
106
oglsdo->needsInit = JNI_TRUE;
107
if (peer != NULL) {
108
RECT insets;
109
AwtComponent_GetInsets(env, peer, &insets);
110
oglsdo->xOffset = -insets.left;
111
oglsdo->yOffset = -insets.bottom;
112
} else {
113
oglsdo->xOffset = 0;
114
oglsdo->yOffset = 0;
115
}
116
117
wglsdo->window = (HWND)jlong_to_ptr(hwnd);
118
wglsdo->configInfo = (WGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
119
if (wglsdo->configInfo == NULL) {
120
free(wglsdo);
121
JNU_ThrowNullPointerException(env, "Config info is null in initOps");
122
}
123
}
124
125
/**
126
* This function disposes of any native windowing system resources associated
127
* with this surface. For instance, if the given OGLSDOps is of type
128
* OGLSD_PBUFFER, this method implementation will destroy the actual pbuffer
129
* surface.
130
*/
131
void
132
OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo)
133
{
134
WGLSDOps *wglsdo = (WGLSDOps *)oglsdo->privOps;
135
136
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface");
137
138
if (oglsdo->drawableType == OGLSD_PBUFFER) {
139
if (wglsdo->pbuffer != 0) {
140
if (wglsdo->pbufferDC != 0) {
141
j2d_wglReleasePbufferDCARB(wglsdo->pbuffer,
142
wglsdo->pbufferDC);
143
wglsdo->pbufferDC = 0;
144
}
145
j2d_wglDestroyPbufferARB(wglsdo->pbuffer);
146
wglsdo->pbuffer = 0;
147
}
148
}
149
}
150
151
/**
152
* Makes the given context current to its associated "scratch" surface. If
153
* the operation is successful, this method will return JNI_TRUE; otherwise,
154
* returns JNI_FALSE.
155
*/
156
static jboolean
157
WGLSD_MakeCurrentToScratch(JNIEnv *env, OGLContext *oglc)
158
{
159
WGLCtxInfo *ctxInfo;
160
161
J2dTraceLn(J2D_TRACE_INFO, "WGLSD_MakeCurrentToScratch");
162
163
if (oglc == NULL) {
164
J2dRlsTraceLn(J2D_TRACE_ERROR,
165
"WGLSD_MakeCurrentToScratch: context is null");
166
return JNI_FALSE;
167
}
168
169
ctxInfo = (WGLCtxInfo *)oglc->ctxInfo;
170
if (!j2d_wglMakeCurrent(ctxInfo->scratchSurfaceDC, ctxInfo->context)) {
171
J2dRlsTraceLn(J2D_TRACE_ERROR,
172
"WGLSD_MakeCurrentToScratch: could not make current");
173
return JNI_FALSE;
174
}
175
176
return JNI_TRUE;
177
}
178
179
/**
180
* Makes the given GraphicsConfig's context current to its associated
181
* "scratch" surface. If there is a problem making the context current,
182
* this method will return NULL; otherwise, returns a pointer to the
183
* OGLContext that is associated with the given GraphicsConfig.
184
*/
185
OGLContext *
186
OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo)
187
{
188
WGLGraphicsConfigInfo *wglInfo =
189
(WGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
190
OGLContext *oglc;
191
192
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SetScratchContext");
193
194
if (wglInfo == NULL) {
195
J2dRlsTraceLn(J2D_TRACE_ERROR,
196
"OGLSD_SetScratchContext: wgl config info is null");
197
return NULL;
198
}
199
200
oglc = wglInfo->context;
201
if (!WGLSD_MakeCurrentToScratch(env, oglc)) {
202
return NULL;
203
}
204
205
if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
206
// the GL_EXT_framebuffer_object extension is present, so this call
207
// will ensure that we are bound to the scratch pbuffer (and not
208
// some other framebuffer object)
209
j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
210
}
211
212
return oglc;
213
}
214
215
/**
216
* Makes a context current to the given source and destination
217
* surfaces. If there is a problem making the context current, this method
218
* will return NULL; otherwise, returns a pointer to the OGLContext that is
219
* associated with the destination surface.
220
*/
221
OGLContext *
222
OGLSD_MakeOGLContextCurrent(JNIEnv *env, OGLSDOps *srcOps, OGLSDOps *dstOps)
223
{
224
WGLSDOps *srcWGLOps = (WGLSDOps *)srcOps->privOps;
225
WGLSDOps *dstWGLOps = (WGLSDOps *)dstOps->privOps;
226
OGLContext *oglc;
227
WGLCtxInfo *ctxinfo;
228
HDC srcHDC, dstHDC;
229
BOOL success;
230
231
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_MakeOGLContextCurrent");
232
233
J2dTraceLn4(J2D_TRACE_VERBOSE, " src: %d %p dst: %d %p",
234
srcOps->drawableType, srcOps,
235
dstOps->drawableType, dstOps);
236
237
oglc = dstWGLOps->configInfo->context;
238
if (oglc == NULL) {
239
J2dRlsTraceLn(J2D_TRACE_ERROR,
240
"OGLSD_MakeOGLContextCurrent: context is null");
241
return NULL;
242
}
243
244
if (dstOps->drawableType == OGLSD_FBOBJECT) {
245
OGLContext *currentContext = OGLRenderQueue_GetCurrentContext();
246
247
// first make sure we have a current context (if the context isn't
248
// already current to some drawable, we will make it current to
249
// its scratch surface)
250
if (oglc != currentContext) {
251
if (!WGLSD_MakeCurrentToScratch(env, oglc)) {
252
return NULL;
253
}
254
}
255
256
// now bind to the fbobject associated with the destination surface;
257
// this means that all rendering will go into the fbobject destination
258
// (note that we unbind the currently bound texture first; this is
259
// recommended procedure when binding an fbobject)
260
j2d_glBindTexture(dstOps->textureTarget, 0);
261
j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID);
262
263
return oglc;
264
}
265
266
ctxinfo = (WGLCtxInfo *)oglc->ctxInfo;
267
268
// get the hdc for the destination surface
269
if (dstOps->drawableType == OGLSD_PBUFFER) {
270
dstHDC = dstWGLOps->pbufferDC;
271
} else {
272
dstHDC = GetDC(dstWGLOps->window);
273
}
274
275
// get the hdc for the source surface
276
if (srcOps->drawableType == OGLSD_PBUFFER) {
277
srcHDC = srcWGLOps->pbufferDC;
278
} else {
279
// the source will always be equal to the destination in this case
280
srcHDC = dstHDC;
281
}
282
283
// REMIND: in theory we should be able to use wglMakeContextCurrentARB()
284
// even when the src/dst surfaces are the same, but this causes problems
285
// on ATI's drivers (see 6525997); for now we will only use it when the
286
// surfaces are different, otherwise we will use the old
287
// wglMakeCurrent() approach...
288
if (srcHDC != dstHDC) {
289
// use WGL_ARB_make_current_read extension to make context current
290
success =
291
j2d_wglMakeContextCurrentARB(dstHDC, srcHDC, ctxinfo->context);
292
} else {
293
// use the old approach for making current to the destination
294
success = j2d_wglMakeCurrent(dstHDC, ctxinfo->context);
295
}
296
if (!success) {
297
J2dRlsTraceLn(J2D_TRACE_ERROR,
298
"OGLSD_MakeOGLContextCurrent: could not make current");
299
if (dstOps->drawableType != OGLSD_PBUFFER) {
300
ReleaseDC(dstWGLOps->window, dstHDC);
301
}
302
return NULL;
303
}
304
305
if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
306
// the GL_EXT_framebuffer_object extension is present, so we
307
// must bind to the default (windowing system provided)
308
// framebuffer
309
j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
310
}
311
312
if (dstOps->drawableType != OGLSD_PBUFFER) {
313
ReleaseDC(dstWGLOps->window, dstHDC);
314
}
315
316
return oglc;
317
}
318
319
/**
320
* This function initializes a native window surface and caches the window
321
* bounds in the given OGLSDOps. Returns JNI_TRUE if the operation was
322
* successful; JNI_FALSE otherwise.
323
*/
324
jboolean
325
OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo)
326
{
327
PIXELFORMATDESCRIPTOR pfd;
328
WGLSDOps *wglsdo;
329
WGLGraphicsConfigInfo *wglInfo;
330
HWND window;
331
RECT wbounds;
332
HDC hdc;
333
334
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow");
335
336
if (oglsdo == NULL) {
337
J2dRlsTraceLn(J2D_TRACE_ERROR,
338
"OGLSD_InitOGLWindow: ops are null");
339
return JNI_FALSE;
340
}
341
342
wglsdo = (WGLSDOps *)oglsdo->privOps;
343
if (wglsdo == NULL) {
344
J2dRlsTraceLn(J2D_TRACE_ERROR,
345
"OGLSD_InitOGLWindow: wgl ops are null");
346
return JNI_FALSE;
347
}
348
349
wglInfo = wglsdo->configInfo;
350
if (wglInfo == NULL) {
351
J2dRlsTraceLn(J2D_TRACE_ERROR,
352
"OGLSD_InitOGLWindow: graphics config info is null");
353
return JNI_FALSE;
354
}
355
356
window = wglsdo->window;
357
if (!IsWindow(window)) {
358
J2dRlsTraceLn(J2D_TRACE_ERROR,
359
"OGLSD_InitOGLWindow: disposed component");
360
return JNI_FALSE;
361
}
362
363
GetWindowRect(window, &wbounds);
364
365
hdc = GetDC(window);
366
if (hdc == 0) {
367
J2dRlsTraceLn(J2D_TRACE_ERROR,
368
"OGLSD_InitOGLWindow: invalid hdc");
369
return JNI_FALSE;
370
}
371
372
if (!SetPixelFormat(hdc, wglInfo->pixfmt, &pfd)) {
373
J2dRlsTraceLn(J2D_TRACE_ERROR,
374
"OGLSD_InitOGLWindow: error setting pixel format");
375
ReleaseDC(window, hdc);
376
return JNI_FALSE;
377
}
378
379
ReleaseDC(window, hdc);
380
381
oglsdo->drawableType = OGLSD_WINDOW;
382
oglsdo->isOpaque = JNI_TRUE;
383
oglsdo->width = wbounds.right - wbounds.left;
384
oglsdo->height = wbounds.bottom - wbounds.top;
385
wglsdo->pbufferDC = 0;
386
387
J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d",
388
oglsdo->width, oglsdo->height);
389
390
return JNI_TRUE;
391
}
392
393
JNIEXPORT jboolean JNICALL
394
Java_sun_java2d_opengl_WGLSurfaceData_initPbuffer
395
(JNIEnv *env, jobject wglsd,
396
jlong pData, jlong pConfigInfo,
397
jboolean isOpaque,
398
jint width, jint height)
399
{
400
int attrKeys[] = {
401
WGL_MAX_PBUFFER_WIDTH_ARB,
402
WGL_MAX_PBUFFER_HEIGHT_ARB,
403
};
404
int attrVals[2];
405
int pbAttrList[] = { 0 };
406
OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData);
407
WGLGraphicsConfigInfo *wglInfo =
408
(WGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
409
WGLSDOps *wglsdo;
410
HWND hwnd;
411
HDC hdc, pbufferDC;
412
HPBUFFERARB pbuffer;
413
int maxWidth, maxHeight;
414
int actualWidth, actualHeight;
415
416
J2dTraceLn3(J2D_TRACE_INFO,
417
"WGLSurfaceData_initPbuffer: w=%d h=%d opq=%d",
418
width, height, isOpaque);
419
420
if (oglsdo == NULL) {
421
J2dRlsTraceLn(J2D_TRACE_ERROR,
422
"WGLSurfaceData_initPbuffer: ops are null");
423
return JNI_FALSE;
424
}
425
426
wglsdo = (WGLSDOps *)oglsdo->privOps;
427
if (wglsdo == NULL) {
428
J2dRlsTraceLn(J2D_TRACE_ERROR,
429
"WGLSurfaceData_initPbuffer: wgl ops are null");
430
return JNI_FALSE;
431
}
432
433
if (wglInfo == NULL) {
434
J2dRlsTraceLn(J2D_TRACE_ERROR,
435
"WGLSurfaceData_initPbuffer: wgl config info is null");
436
return JNI_FALSE;
437
}
438
439
// create a scratch window
440
hwnd = WGLGC_CreateScratchWindow(wglInfo->screen);
441
if (hwnd == 0) {
442
J2dRlsTraceLn(J2D_TRACE_ERROR,
443
"WGLSurfaceData_initPbuffer: could not create scratch window");
444
return JNI_FALSE;
445
}
446
447
// get the HDC for the scratch window
448
hdc = GetDC(hwnd);
449
if (hdc == 0) {
450
J2dRlsTraceLn(J2D_TRACE_ERROR,
451
"WGLSurfaceData_initPbuffer: could not get dc for scratch window");
452
DestroyWindow(hwnd);
453
return JNI_FALSE;
454
}
455
456
// get the maximum allowable pbuffer dimensions
457
j2d_wglGetPixelFormatAttribivARB(hdc, wglInfo->pixfmt, 0, 2,
458
attrKeys, attrVals);
459
maxWidth = attrVals[0];
460
maxHeight = attrVals[1];
461
462
J2dTraceLn4(J2D_TRACE_VERBOSE,
463
" desired pbuffer dimensions: w=%d h=%d maxw=%d maxh=%d",
464
width, height, maxWidth, maxHeight);
465
466
// if either dimension is 0 or larger than the maximum, we cannot
467
// allocate a pbuffer with the requested dimensions
468
if (width == 0 || width > maxWidth ||
469
height == 0 || height > maxHeight)
470
{
471
J2dRlsTraceLn(J2D_TRACE_ERROR,
472
"WGLSurfaceData_initPbuffer: invalid dimensions");
473
ReleaseDC(hwnd, hdc);
474
DestroyWindow(hwnd);
475
return JNI_FALSE;
476
}
477
478
pbuffer = j2d_wglCreatePbufferARB(hdc, wglInfo->pixfmt,
479
width, height, pbAttrList);
480
481
ReleaseDC(hwnd, hdc);
482
DestroyWindow(hwnd);
483
484
if (pbuffer == 0) {
485
J2dRlsTraceLn(J2D_TRACE_ERROR,
486
"WGLSurfaceData_initPbuffer: could not create wgl pbuffer");
487
return JNI_FALSE;
488
}
489
490
// note that we get the DC for the pbuffer at creation time, and then
491
// release the DC when the pbuffer is disposed; the WGL_ARB_pbuffer
492
// spec is vague about such things, but from past experience we know
493
// this approach to be more robust than, for example, doing a
494
// Get/ReleasePbufferDC() everytime we make a context current
495
pbufferDC = j2d_wglGetPbufferDCARB(pbuffer);
496
if (pbufferDC == 0) {
497
J2dRlsTraceLn(J2D_TRACE_ERROR,
498
"WGLSurfaceData_initPbuffer: could not get dc for pbuffer");
499
j2d_wglDestroyPbufferARB(pbuffer);
500
return JNI_FALSE;
501
}
502
503
// make sure the actual dimensions match those that we requested
504
j2d_wglQueryPbufferARB(pbuffer, WGL_PBUFFER_WIDTH_ARB, &actualWidth);
505
j2d_wglQueryPbufferARB(pbuffer, WGL_PBUFFER_HEIGHT_ARB, &actualHeight);
506
507
if (width != actualWidth || height != actualHeight) {
508
J2dRlsTraceLn2(J2D_TRACE_ERROR,
509
"WGLSurfaceData_initPbuffer: actual (w=%d h=%d) != requested",
510
actualWidth, actualHeight);
511
j2d_wglReleasePbufferDCARB(pbuffer, pbufferDC);
512
j2d_wglDestroyPbufferARB(pbuffer);
513
return JNI_FALSE;
514
}
515
516
oglsdo->drawableType = OGLSD_PBUFFER;
517
oglsdo->isOpaque = isOpaque;
518
oglsdo->width = width;
519
oglsdo->height = height;
520
wglsdo->pbuffer = pbuffer;
521
wglsdo->pbufferDC = pbufferDC;
522
523
OGLSD_SetNativeDimensions(env, oglsdo, width, height);
524
525
return JNI_TRUE;
526
}
527
528
void
529
OGLSD_SwapBuffers(JNIEnv *env, jlong pPeerData)
530
{
531
HWND window;
532
HDC hdc;
533
534
J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers");
535
536
window = AwtComponent_GetHWnd(env, pPeerData);
537
if (!IsWindow(window)) {
538
J2dRlsTraceLn(J2D_TRACE_ERROR,
539
"OGLSD_SwapBuffers: disposed component");
540
return;
541
}
542
543
hdc = GetDC(window);
544
if (hdc == 0) {
545
J2dRlsTraceLn(J2D_TRACE_ERROR,
546
"OGLSD_SwapBuffers: invalid hdc");
547
return;
548
}
549
550
if (!SwapBuffers(hdc)) {
551
J2dRlsTraceLn(J2D_TRACE_ERROR,
552
"OGLSD_SwapBuffers: error in SwapBuffers");
553
}
554
555
if (!ReleaseDC(window, hdc)) {
556
J2dRlsTraceLn(J2D_TRACE_ERROR,
557
"OGLSD_SwapBuffers: error while releasing dc");
558
}
559
}
560
561
// needed by Mac OS X port, no-op on other platforms
562
void
563
OGLSD_Flush(JNIEnv *env)
564
{
565
}
566
567
/*
568
* Class: sun_java2d_opengl_WGLSurfaceData
569
* Method: updateWindowAccelImpl
570
* Signature: (JJII)Z
571
*/
572
JNIEXPORT jboolean JNICALL
573
Java_sun_java2d_opengl_WGLSurfaceData_updateWindowAccelImpl
574
(JNIEnv *env, jclass clazz, jlong pData, jobject peer, jint w, jint h)
575
{
576
OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData);
577
OGLPixelFormat pf = PixelFormats[0/*PF_INT_ARGB_PRE*/];
578
HBITMAP hBitmap = NULL;
579
void *pDst;
580
jint srcx, srcy, dstx, dsty, width, height;
581
jint pixelStride = 4;
582
jint scanStride = pixelStride * w;
583
584
J2dTraceLn(J2D_TRACE_INFO, "WGLSurfaceData_updateWindowAccelImpl");
585
586
if (w <= 0 || h <= 0) {
587
return JNI_TRUE;
588
}
589
if (oglsdo == NULL) {
590
return JNI_FALSE;
591
}
592
RESET_PREVIOUS_OP();
593
594
width = w;
595
height = h;
596
srcx = srcy = dstx = dsty = 0;
597
598
pDst = SAFE_SIZE_ARRAY_ALLOC(malloc, height, scanStride);
599
if (pDst == NULL) {
600
return JNI_FALSE;
601
}
602
ZeroMemory(pDst, height * scanStride);
603
604
// the code below is mostly copied from OGLBlitLoops_SurfaceToSwBlit
605
606
j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, dstx);
607
j2d_glPixelStorei(GL_PACK_ROW_LENGTH, scanStride / pixelStride);
608
j2d_glPixelStorei(GL_PACK_ALIGNMENT, pf.alignment);
609
610
// this accounts for lower-left origin of the source region
611
srcx = oglsdo->xOffset + srcx;
612
srcy = oglsdo->yOffset + oglsdo->height - (srcy + 1);
613
// we must read one scanline at a time because there is no way
614
// to read starting at the top-left corner of the source region
615
while (height > 0) {
616
j2d_glPixelStorei(GL_PACK_SKIP_ROWS, dsty);
617
j2d_glReadPixels(srcx, srcy, width, 1,
618
pf.format, pf.type, pDst);
619
srcy--;
620
dsty++;
621
height--;
622
}
623
624
j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
625
j2d_glPixelStorei(GL_PACK_SKIP_ROWS, 0);
626
j2d_glPixelStorei(GL_PACK_ROW_LENGTH, 0);
627
j2d_glPixelStorei(GL_PACK_ALIGNMENT, 4);
628
629
// the pixels read from the surface are already premultiplied
630
hBitmap = BitmapUtil_CreateBitmapFromARGBPre(w, h, scanStride,
631
(int*)pDst);
632
free(pDst);
633
634
if (hBitmap == NULL) {
635
return JNI_FALSE;
636
}
637
638
AwtWindow_UpdateWindow(env, peer, w, h, hBitmap);
639
640
// hBitmap is released in UpdateWindow
641
642
return JNI_TRUE;
643
}
644
645