105 } |
105 } |
106 } |
106 } |
107 |
107 |
108 /** |
108 /** |
109 * This function disposes of any native windowing system resources associated |
109 * This function disposes of any native windowing system resources associated |
110 * with this surface. For instance, if the given OGLSDOps is of type |
110 * with this surface. |
111 * OGLSD_PBUFFER, this method implementation will destroy the actual pbuffer |
|
112 * surface. |
|
113 */ |
111 */ |
114 void |
112 void |
115 OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo) |
113 OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo) |
116 { |
114 { |
117 WGLSDOps *wglsdo = (WGLSDOps *)oglsdo->privOps; |
|
118 |
|
119 J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface"); |
115 J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface"); |
120 |
116 // Window is free'd later by AWT code... |
121 if (oglsdo->drawableType == OGLSD_PBUFFER) { |
|
122 if (wglsdo->pbuffer != 0) { |
|
123 if (wglsdo->pbufferDC != 0) { |
|
124 j2d_wglReleasePbufferDCARB(wglsdo->pbuffer, |
|
125 wglsdo->pbufferDC); |
|
126 wglsdo->pbufferDC = 0; |
|
127 } |
|
128 j2d_wglDestroyPbufferARB(wglsdo->pbuffer); |
|
129 wglsdo->pbuffer = 0; |
|
130 } |
|
131 } |
|
132 } |
117 } |
133 |
118 |
134 /** |
119 /** |
135 * Makes the given context current to its associated "scratch" surface. If |
120 * Makes the given context current to its associated "scratch" surface. If |
136 * the operation is successful, this method will return JNI_TRUE; otherwise, |
121 * the operation is successful, this method will return JNI_TRUE; otherwise, |
274 } |
259 } |
275 |
260 |
276 ctxinfo = (WGLCtxInfo *)oglc->ctxInfo; |
261 ctxinfo = (WGLCtxInfo *)oglc->ctxInfo; |
277 |
262 |
278 // get the hdc for the destination surface |
263 // get the hdc for the destination surface |
279 if (dstOps->drawableType == OGLSD_PBUFFER) { |
264 dstHDC = GetDC(dstWGLOps->window); |
280 dstHDC = dstWGLOps->pbufferDC; |
|
281 } else { |
|
282 dstHDC = GetDC(dstWGLOps->window); |
|
283 } |
|
284 |
265 |
285 // get the hdc for the source surface |
266 // get the hdc for the source surface |
286 if (srcOps->drawableType == OGLSD_PBUFFER) { |
267 // the source will always be equal to the destination in this case |
287 srcHDC = srcWGLOps->pbufferDC; |
268 srcHDC = dstHDC; |
288 } else { |
|
289 // the source will always be equal to the destination in this case |
|
290 srcHDC = dstHDC; |
|
291 } |
|
292 |
269 |
293 // REMIND: in theory we should be able to use wglMakeContextCurrentARB() |
270 // REMIND: in theory we should be able to use wglMakeContextCurrentARB() |
294 // even when the src/dst surfaces are the same, but this causes problems |
271 // even when the src/dst surfaces are the same, but this causes problems |
295 // on ATI's drivers (see 6525997); for now we will only use it when the |
272 // on ATI's drivers (see 6525997); for now we will only use it when the |
296 // surfaces are different, otherwise we will use the old |
273 // surfaces are different, otherwise we will use the old |
304 success = j2d_wglMakeCurrent(dstHDC, ctxinfo->context); |
281 success = j2d_wglMakeCurrent(dstHDC, ctxinfo->context); |
305 } |
282 } |
306 if (!success) { |
283 if (!success) { |
307 J2dRlsTraceLn(J2D_TRACE_ERROR, |
284 J2dRlsTraceLn(J2D_TRACE_ERROR, |
308 "OGLSD_MakeOGLContextCurrent: could not make current"); |
285 "OGLSD_MakeOGLContextCurrent: could not make current"); |
309 if (dstOps->drawableType != OGLSD_PBUFFER) { |
286 ReleaseDC(dstWGLOps->window, dstHDC); |
310 ReleaseDC(dstWGLOps->window, dstHDC); |
|
311 } |
|
312 return NULL; |
287 return NULL; |
313 } |
288 } |
314 |
289 |
315 if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) { |
290 if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) { |
316 // the GL_EXT_framebuffer_object extension is present, so we |
291 // the GL_EXT_framebuffer_object extension is present, so we |
317 // must bind to the default (windowing system provided) |
292 // must bind to the default (windowing system provided) |
318 // framebuffer |
293 // framebuffer |
319 j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
294 j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
320 } |
295 } |
321 |
296 |
322 if (dstOps->drawableType != OGLSD_PBUFFER) { |
297 ReleaseDC(dstWGLOps->window, dstHDC); |
323 ReleaseDC(dstWGLOps->window, dstHDC); |
|
324 } |
|
325 |
298 |
326 return oglc; |
299 return oglc; |
327 } |
300 } |
328 |
301 |
329 /** |
302 /** |
394 oglsdo->height = wbounds.bottom - wbounds.top; |
367 oglsdo->height = wbounds.bottom - wbounds.top; |
395 wglsdo->pbufferDC = 0; |
368 wglsdo->pbufferDC = 0; |
396 |
369 |
397 J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", |
370 J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", |
398 oglsdo->width, oglsdo->height); |
371 oglsdo->width, oglsdo->height); |
399 |
|
400 return JNI_TRUE; |
|
401 } |
|
402 |
|
403 JNIEXPORT jboolean JNICALL |
|
404 Java_sun_java2d_opengl_WGLSurfaceData_initPbuffer |
|
405 (JNIEnv *env, jobject wglsd, |
|
406 jlong pData, jlong pConfigInfo, |
|
407 jboolean isOpaque, |
|
408 jint width, jint height) |
|
409 { |
|
410 int attrKeys[] = { |
|
411 WGL_MAX_PBUFFER_WIDTH_ARB, |
|
412 WGL_MAX_PBUFFER_HEIGHT_ARB, |
|
413 }; |
|
414 int attrVals[2]; |
|
415 int pbAttrList[] = { 0 }; |
|
416 OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); |
|
417 WGLGraphicsConfigInfo *wglInfo = |
|
418 (WGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); |
|
419 WGLSDOps *wglsdo; |
|
420 HWND hwnd; |
|
421 HDC hdc, pbufferDC; |
|
422 HPBUFFERARB pbuffer; |
|
423 int maxWidth, maxHeight; |
|
424 int actualWidth, actualHeight; |
|
425 |
|
426 J2dTraceLn3(J2D_TRACE_INFO, |
|
427 "WGLSurfaceData_initPbuffer: w=%d h=%d opq=%d", |
|
428 width, height, isOpaque); |
|
429 |
|
430 if (oglsdo == NULL) { |
|
431 J2dRlsTraceLn(J2D_TRACE_ERROR, |
|
432 "WGLSurfaceData_initPbuffer: ops are null"); |
|
433 return JNI_FALSE; |
|
434 } |
|
435 |
|
436 wglsdo = (WGLSDOps *)oglsdo->privOps; |
|
437 if (wglsdo == NULL) { |
|
438 J2dRlsTraceLn(J2D_TRACE_ERROR, |
|
439 "WGLSurfaceData_initPbuffer: wgl ops are null"); |
|
440 return JNI_FALSE; |
|
441 } |
|
442 |
|
443 if (wglInfo == NULL) { |
|
444 J2dRlsTraceLn(J2D_TRACE_ERROR, |
|
445 "WGLSurfaceData_initPbuffer: wgl config info is null"); |
|
446 return JNI_FALSE; |
|
447 } |
|
448 |
|
449 // create a scratch window |
|
450 hwnd = WGLGC_CreateScratchWindow(wglInfo->screen); |
|
451 if (hwnd == 0) { |
|
452 J2dRlsTraceLn(J2D_TRACE_ERROR, |
|
453 "WGLSurfaceData_initPbuffer: could not create scratch window"); |
|
454 return JNI_FALSE; |
|
455 } |
|
456 |
|
457 // get the HDC for the scratch window |
|
458 hdc = GetDC(hwnd); |
|
459 if (hdc == 0) { |
|
460 J2dRlsTraceLn(J2D_TRACE_ERROR, |
|
461 "WGLSurfaceData_initPbuffer: could not get dc for scratch window"); |
|
462 DestroyWindow(hwnd); |
|
463 return JNI_FALSE; |
|
464 } |
|
465 |
|
466 // get the maximum allowable pbuffer dimensions |
|
467 j2d_wglGetPixelFormatAttribivARB(hdc, wglInfo->pixfmt, 0, 2, |
|
468 attrKeys, attrVals); |
|
469 maxWidth = attrVals[0]; |
|
470 maxHeight = attrVals[1]; |
|
471 |
|
472 J2dTraceLn4(J2D_TRACE_VERBOSE, |
|
473 " desired pbuffer dimensions: w=%d h=%d maxw=%d maxh=%d", |
|
474 width, height, maxWidth, maxHeight); |
|
475 |
|
476 // if either dimension is 0 or larger than the maximum, we cannot |
|
477 // allocate a pbuffer with the requested dimensions |
|
478 if (width == 0 || width > maxWidth || |
|
479 height == 0 || height > maxHeight) |
|
480 { |
|
481 J2dRlsTraceLn(J2D_TRACE_ERROR, |
|
482 "WGLSurfaceData_initPbuffer: invalid dimensions"); |
|
483 ReleaseDC(hwnd, hdc); |
|
484 DestroyWindow(hwnd); |
|
485 return JNI_FALSE; |
|
486 } |
|
487 |
|
488 pbuffer = j2d_wglCreatePbufferARB(hdc, wglInfo->pixfmt, |
|
489 width, height, pbAttrList); |
|
490 |
|
491 ReleaseDC(hwnd, hdc); |
|
492 DestroyWindow(hwnd); |
|
493 |
|
494 if (pbuffer == 0) { |
|
495 J2dRlsTraceLn(J2D_TRACE_ERROR, |
|
496 "WGLSurfaceData_initPbuffer: could not create wgl pbuffer"); |
|
497 return JNI_FALSE; |
|
498 } |
|
499 |
|
500 // note that we get the DC for the pbuffer at creation time, and then |
|
501 // release the DC when the pbuffer is disposed; the WGL_ARB_pbuffer |
|
502 // spec is vague about such things, but from past experience we know |
|
503 // this approach to be more robust than, for example, doing a |
|
504 // Get/ReleasePbufferDC() everytime we make a context current |
|
505 pbufferDC = j2d_wglGetPbufferDCARB(pbuffer); |
|
506 if (pbufferDC == 0) { |
|
507 J2dRlsTraceLn(J2D_TRACE_ERROR, |
|
508 "WGLSurfaceData_initPbuffer: could not get dc for pbuffer"); |
|
509 j2d_wglDestroyPbufferARB(pbuffer); |
|
510 return JNI_FALSE; |
|
511 } |
|
512 |
|
513 // make sure the actual dimensions match those that we requested |
|
514 j2d_wglQueryPbufferARB(pbuffer, WGL_PBUFFER_WIDTH_ARB, &actualWidth); |
|
515 j2d_wglQueryPbufferARB(pbuffer, WGL_PBUFFER_HEIGHT_ARB, &actualHeight); |
|
516 |
|
517 if (width != actualWidth || height != actualHeight) { |
|
518 J2dRlsTraceLn2(J2D_TRACE_ERROR, |
|
519 "WGLSurfaceData_initPbuffer: actual (w=%d h=%d) != requested", |
|
520 actualWidth, actualHeight); |
|
521 j2d_wglReleasePbufferDCARB(pbuffer, pbufferDC); |
|
522 j2d_wglDestroyPbufferARB(pbuffer); |
|
523 return JNI_FALSE; |
|
524 } |
|
525 |
|
526 oglsdo->drawableType = OGLSD_PBUFFER; |
|
527 oglsdo->isOpaque = isOpaque; |
|
528 oglsdo->width = width; |
|
529 oglsdo->height = height; |
|
530 wglsdo->pbuffer = pbuffer; |
|
531 wglsdo->pbufferDC = pbufferDC; |
|
532 |
|
533 OGLSD_SetNativeDimensions(env, oglsdo, width, height); |
|
534 |
372 |
535 return JNI_TRUE; |
373 return JNI_TRUE; |
536 } |
374 } |
537 |
375 |
538 void |
376 void |