/** * Creates a context that is compatible with the given pixel format * identifier. Returns 0 if the context could not be created properly. */ static HGLRC WGLGC_CreateContext(jint screennum, jint pixfmt) { PIXELFORMATDESCRIPTOR pfd; HWND hwnd; HDC hdc; HGLRC hglrc; J2dTraceLn(J2D_TRACE_INFO, "in WGLGC_CreateContext"); hwnd = WGLGC_CreateScratchWindow(screennum); if (hwnd == 0) { J2dTraceLn(J2D_TRACE_ERROR, "could not create scratch window"); return 0; } // get the HDC for the scratch window hdc = GetDC(hwnd); if (hdc == 0) { J2dTraceLn(J2D_TRACE_ERROR, "could not get dc for scratch window"); DestroyWindow(hwnd); return 0; } // set the pixel format for the scratch window if (!SetPixelFormat(hdc, pixfmt, &pfd)) { J2dTraceLn(J2D_TRACE_ERROR, "error setting pixel format"); ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); return 0; } // create a context based on the scratch window hglrc = j2d_wglCreateContext(hdc); // release the temporary resources ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); return hglrc; }
/** * Convenience method that calls GLXGraphicsConfig.getThreadSharedContext(), * which will fetch the shared context for the current thread, and make that * shared context current. Returns a pointer to the native shared OGLContext. */ OGLContext * OGLSD_GetSharedContext(JNIEnv *env) { jlong oglc; J2dTraceLn(J2D_TRACE_INFO, "in OGLSD_GetSharedContext"); oglc = (*env)->CallStaticLongMethod(env, glxgcClass, getSharedContextID); return (OGLContext *)jlong_to_ptr(oglc); }
/* * Method: Win32BBSD_Dispose */ void Win32BBSD_Dispose(JNIEnv *env, SurfaceDataOps *ops) { // ops is assumed non-null as it is checked in SurfaceData_DisposeOps Win32SDOps *wsdo = (Win32SDOps*)ops; J2dTraceLn(J2D_TRACE_INFO, "Win32BBSD_Dispose"); if (wsdo->lpSurface != NULL && !wsdo->surfaceLost) { delete wsdo->lpSurface; wsdo->lpSurface = NULL; } disposeOSSD_WSDO(env, wsdo); }
JNIEXPORT void JNICALL Java_sun_java2d_xr_XRSurfaceData_initIDs(JNIEnv *env, jclass xsd) { #ifndef HEADLESS J2dTraceLn(J2D_TRACE_INFO, "in XRSurfaceData_initIDs"); pictID = (*env)->GetFieldID(env, xsd, "picture", "I"); xidID = (*env)->GetFieldID(env, xsd, "xid", "I"); XShared_initIDs(env, JNI_FALSE); #endif /* !HEADLESS */ }
void GetFlagValues(JNIEnv *env, jclass wFlagsClass) { jboolean d3dEnabled = env->GetStaticBooleanField(wFlagsClass, d3dEnabledID); jboolean d3dSet = env->GetStaticBooleanField(wFlagsClass, d3dSetID); if (!d3dSet) { // Only check environment variable if user did not set Java // command-line parameter; values of sun.java2d.d3d override // any setting of J2D_D3D environment variable. char *d3dEnv = getenv("J2D_D3D"); if (d3dEnv) { if (strcmp(d3dEnv, "false") == 0) { // printf("Java2D Direct3D usage disabled by J2D_D3D env\n"); d3dEnabled = FALSE; d3dSet = TRUE; SetD3DEnabledFlag(env, d3dEnabled, d3dSet); } else if (strcmp(d3dEnv, "true") == 0) { // printf("Java2D Direct3D usage forced on by J2D_D3D env\n"); d3dEnabled = TRUE; d3dSet = TRUE; SetD3DEnabledFlag(env, d3dEnabled, d3dSet); } } } useD3D = d3dEnabled; forceD3DUsage = d3dSet; g_offscreenSharing = GetStaticBoolean(env, wFlagsClass, "offscreenSharingEnabled"); accelReset = GetStaticBoolean(env, wFlagsClass, "accelReset"); checkRegistry = GetStaticBoolean(env, wFlagsClass, "checkRegistry"); disableRegistry = GetStaticBoolean(env, wFlagsClass, "disableRegistry"); jstring javaVersionString = (jstring)GetStaticObject(env, wFlagsClass, "javaVersion", "Ljava/lang/String;"); setHighDPIAware = (IS_WINVISTA && GetStaticBoolean(env, wFlagsClass, "setHighDPIAware")); J2dTraceLn(J2D_TRACE_INFO, "WindowsFlags (native):"); J2dTraceLn1(J2D_TRACE_INFO, " d3dEnabled = %s", (useD3D ? "true" : "false")); J2dTraceLn1(J2D_TRACE_INFO, " d3dSet = %s", (forceD3DUsage ? "true" : "false")); J2dTraceLn1(J2D_TRACE_INFO, " offscreenSharing = %s", (g_offscreenSharing ? "true" : "false")); J2dTraceLn1(J2D_TRACE_INFO, " accelReset = %s", (accelReset ? "true" : "false")); J2dTraceLn1(J2D_TRACE_INFO, " checkRegistry = %s", (checkRegistry ? "true" : "false")); J2dTraceLn1(J2D_TRACE_INFO, " disableRegistry = %s", (disableRegistry ? "true" : "false")); J2dTraceLn1(J2D_TRACE_INFO, " setHighDPIAware = %s", (setHighDPIAware ? "true" : "false")); }
/** * Creates a scratch pbuffer, which can be used to make a context current * for extension queries, etc. */ static GLXPbuffer GLXGC_InitScratchPbuffer(GLXFBConfig fbconfig) { int pbattrlist[] = {GLX_PBUFFER_WIDTH, 4, GLX_PBUFFER_HEIGHT, 4, GLX_PRESERVED_CONTENTS, GL_FALSE, 0}; J2dTraceLn(J2D_TRACE_INFO, "GLXGC_InitScratchPbuffer"); return j2d_glXCreatePbuffer(awt_display, fbconfig, pbattrlist); }
/** * Initializes a small texture tile for use with tiled blit operations (see * OGLBlitLoops.c and OGLMaskBlit.c for usage examples). The texture ID for * the tile is stored in the given OGLContext. The tile is initially filled * with garbage values, but the tile is updated as needed (via * glTexSubImage2D()) with real RGBA values used in tiled blit situations. * The internal format for the texture is GL_RGBA8, which should be sufficient * for storing system memory surfaces of any known format (see PixelFormats * for a list of compatible surface formats). */ jboolean OGLContext_InitBlitTileTexture(OGLContext *oglc) { J2dTraceLn(J2D_TRACE_INFO, "OGLContext_InitBlitTileTexture"); oglc->blitTextureID = OGLContext_CreateBlitTexture(GL_RGBA8, GL_RGBA, OGLC_BLIT_TILE_SIZE, OGLC_BLIT_TILE_SIZE); return JNI_TRUE; }
D3DGlyphCache::~D3DGlyphCache() { J2dTraceLn(J2D_TRACE_INFO, "D3DGlyphCache::~D3DGlyphCache"); ReleaseDefPoolResources(); pCtx = NULL; if (pGlyphCache != NULL) { AccelGlyphCache_Free(pGlyphCache); pGlyphCache = NULL; } }
HRESULT D3DGlyphCache::CheckGlyphCacheByteOrder(jboolean rgbOrder) { J2dTraceLn(J2D_TRACE_INFO, "D3DGlyphCache::CheckGlyphCacheByteOrder"); if (gcType != CACHE_LCD) { J2dTraceLn(J2D_TRACE_ERROR, "D3DGlyphCache::CheckGlyphCacheByteOrder"\ " invoked on CACHE_GRAY cache type instance!"); return E_FAIL; } if (rgbOrder != lastRGBOrder) { // need to invalidate the cache in this case; see comments // for lastRGBOrder AccelGlyphCache_Invalidate(pGlyphCache); lastRGBOrder = rgbOrder; } tileFormat = rgbOrder ? TILEFMT_3BYTE_RGB : TILEFMT_3BYTE_BGR; return S_OK; }
JNIEXPORT void JNICALL Java_sun_java2d_opengl_GLXSurfaceData_initIDs(JNIEnv *env, jclass glxsd, jclass glxgc) { #ifndef HEADLESS J2dTraceLn(J2D_TRACE_INFO, "in GLXSurfaceData_initIDs"); glxgcClass = (*env)->NewGlobalRef(env, glxgc); getSharedContextID = (*env)->GetStaticMethodID(env, glxgc, "getThreadSharedContext", "()J"); #endif /* HEADLESS */ }
JNIEXPORT jboolean JNICALL Java_sun_java2d_opengl_GLXContext_makeNativeContextCurrent(JNIEnv *env, jobject glxc, jlong pCtx, jlong pSrc, jlong pDst) { OGLContext *oglc = (OGLContext *)jlong_to_ptr(pCtx); OGLSDOps *srcOps = (OGLSDOps *)jlong_to_ptr(pSrc); OGLSDOps *dstOps = (OGLSDOps *)jlong_to_ptr(pDst); GLXCtxInfo *ctxinfo; GLXSDOps *srcGLXOps; GLXSDOps *dstGLXOps; J2dTraceLn(J2D_TRACE_INFO, "in GLXContext_makeNativeContextCurrent"); if (srcOps == NULL || dstOps == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "ops are null"); return JNI_FALSE; } if (oglc == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "context is null"); return JNI_FALSE; } ctxinfo = (GLXCtxInfo *)oglc->ctxInfo; srcGLXOps = (GLXSDOps *)srcOps->privOps; dstGLXOps = (GLXSDOps *)dstOps->privOps; if (!j2d_glXMakeContextCurrent(awt_display, dstGLXOps->drawable, srcGLXOps->drawable, ctxinfo->context)) { J2dTraceLn(J2D_TRACE_ERROR, "could not make GLX context current"); return JNI_FALSE; } return JNI_TRUE; }
void OGLSD_SwapBuffers(JNIEnv *env, jlong window) { J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers"); if (window == 0L) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_SwapBuffers: window is null"); return; } j2d_glXSwapBuffers(awt_display, (Window)window); }
HWND D3DPipelineManager::GetCurrentFocusWindow() { J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GetCurrentFocusWindow"); if (currentFSFocusAdapter < 0) { J2dTraceLn1(J2D_TRACE_VERBOSE, " no fs windows, using default focus window=0x%x", defaultFocusWindow); return defaultFocusWindow; } J2dTraceLn1(J2D_TRACE_VERBOSE, " using fs window=0x%x", pAdapters[currentFSFocusAdapter].fsFocusWindow); return pAdapters[currentFSFocusAdapter].fsFocusWindow; }
/** * Add cell info to the head of the glyph's list of cached cells. */ void AccelGlyphCache_AddCellInfo(GlyphInfo *glyph, CacheCellInfo *cellInfo) { // assert (glyph != NULL && cellInfo != NULL) J2dTraceLn(J2D_TRACE_INFO, "AccelGlyphCache_AddCellInfo"); J2dTraceLn2(J2D_TRACE_VERBOSE, " glyph 0x%x: adding cell 0x%x to the list", glyph, cellInfo); cellInfo->glyphInfo = glyph; cellInfo->nextGCI = glyph->cellInfo; glyph->cellInfo = cellInfo; glyph->managed = MANAGED_GLYPH; }
/** * Destroys the OpenGL resources associated with the given OGLContext. * It is required that the native context associated with the OGLContext * be made current prior to calling this method. */ void OGLContext_DestroyContextResources(OGLContext *oglc) { J2dTraceLn(J2D_TRACE_INFO, "OGLContext_DestroyContextResources"); if (oglc->xformMatrix != NULL) { free(oglc->xformMatrix); } if (oglc->blitTextureID != 0) { j2d_glDeleteTextures(1, &oglc->blitTextureID); } }
JNIEXPORT jint JNICALL Java_sun_java2d_opengl_WGLGraphicsConfig_getDefaultPixFmt(JNIEnv *env, jclass wglgc, jint screennum) { J2dTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_getDefaultPixFmt"); // REMIND: eventually we should implement this method so that it finds // the most appropriate default pixel format for the given // device; for now, we'll just return 0, and then we'll find // an appropriate pixel format in WGLGC_GetWGLConfigInfo()... return 0; }
JNIEXPORT jlong JNICALL Java_sun_java2d_opengl_WGLGraphicsConfig_initNativeSharedContext (JNIEnv *env, jobject wglsd) { OGLContext *oglc; J2dTraceLn(J2D_TRACE_INFO, "in WGLGraphicsConfig_initNativeSharedContext"); if (sharedContext == NULL || sharedConfigInfo == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "shared context not yet inited"); return 0L; } oglc = WGLGC_InitOGLContext(env, sharedConfigInfo, JNI_TRUE); if (oglc == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "could not create native shared context"); return 0L; } return ptr_to_jlong(oglc); }
/* * Class: sun_java2d_d3d_D3DSurfaceData * Method: dbSetPixelNative * Signature: (JIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_d3d_D3DSurfaceData_dbSetPixelNative (JNIEnv *env, jclass clazz, jlong pData, jint x, jint y, jint pixel) { HRESULT res; D3DSDOps *d3dsdo; D3DResource *pLockableRes; D3DContext *pCtx; D3DPipelineManager *pMgr; J2dTraceLn(J2D_TRACE_INFO, "D3DSurfaceData_dbSetPixelNative"); RETURN_IF_NULL(d3dsdo = (D3DSDOps *)jlong_to_ptr(pData)); RETURN_IF_NULL(d3dsdo->pResource); RETURN_IF_NULL(pMgr = D3DPipelineManager::GetInstance()); if (FAILED(res = pMgr->GetD3DContext(d3dsdo->adapter, &pCtx))) { D3DRQ_MarkLostIfNeeded(res, d3dsdo); return; } RETURN_IF_NULL(pCtx->GetResourceManager()); IDirect3DDevice9 *pd3dDevice = pCtx->Get3DDevice(); IDirect3DSurface9 *pSrc = d3dsdo->pResource->GetSurface(); D3DFORMAT srcFmt = d3dsdo->pResource->GetDesc()->Format; pCtx->UpdateState(STATE_OTHEROP); res = pCtx->GetResourceManager()-> GetLockableRTSurface(1, 1, srcFmt, &pLockableRes); if (SUCCEEDED(res)) { IDirect3DSurface9 *pTmpSurface; D3DLOCKED_RECT lRect; RECT srcRect = { 0l, 0l, 1, 1 }; RECT dstRect = { x, y, x+1, y+1}; pTmpSurface = pLockableRes->GetSurface(); res = pTmpSurface->LockRect(&lRect, &srcRect, D3DLOCK_NOSYSLOCK); if (SUCCEEDED(res)) { if (srcFmt == D3DFMT_X8R8G8B8) { *(jint*)lRect.pBits = pixel; } else { *(unsigned short*)lRect.pBits = (unsigned short)pixel; } pTmpSurface->UnlockRect(); res = pd3dDevice->StretchRect(pTmpSurface, &srcRect, pSrc, &dstRect, D3DTEXF_NONE); } } D3DRQ_MarkLostIfNeeded(res, d3dsdo); }
HRESULT D3DVertexCacher::CreateInstance(D3DContext *pCtx, D3DVertexCacher **ppVC) { HRESULT res; J2dTraceLn(J2D_TRACE_INFO, "D3DVertexCacher::CreateInstance"); *ppVC = new D3DVertexCacher(); if (FAILED(res = (*ppVC)->Init(pCtx))) { delete *ppVC; *ppVC = NULL; } return res; }
HRESULT D3DMaskCache::CreateInstance(D3DContext *pCtx, D3DMaskCache **ppMaskCache) { HRESULT res; J2dTraceLn(J2D_TRACE_INFO, "D3DMaskCache::CreateInstance"); *ppMaskCache = new D3DMaskCache(); if (FAILED(res = (*ppMaskCache)->Init(pCtx))) { delete *ppMaskCache; *ppMaskCache = NULL; } return res; }
void OGLTR_DisableGlyphVertexCache(OGLContext *oglc) { J2dTraceLn(J2D_TRACE_INFO, "OGLTR_DisableGlyphVertexCache"); OGLVertexCache_FlushVertexCache(); OGLVertexCache_RestoreColorState(oglc); j2d_glDisable(GL_TEXTURE_2D); j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 4); j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); }
JNIEXPORT jlong JNICALL Java_sun_java2d_opengl_GLXGraphicsConfig_getGLXConfigInfo(JNIEnv *env, jclass glxgc, jint screennum, jint visnum) { #ifndef HEADLESS J2dTraceLn(J2D_TRACE_INFO, "in GLXGraphicsConfig_getGLXConfigInfo"); return GLXGC_GetGLXConfigInfo(env, screennum, visnum); #else return 0; #endif /* !HEADLESS */ }
HRESULT D3DBufImgOps_DisableConvolveOp(D3DContext *d3dc) { IDirect3DDevice9 *pd3dDevice; J2dTraceLn(J2D_TRACE_INFO, "D3DBufImgOps_DisableConvolveOp"); RETURN_STATUS_IF_NULL(d3dc, E_FAIL); d3dc->UpdateState(STATE_CHANGE); // disable the ConvolveOp shader pd3dDevice = d3dc->Get3DDevice(); return pd3dDevice->SetPixelShader(NULL); }
void OGLRenderer_FillRect(OGLContext *oglc, jint x, jint y, jint w, jint h) { J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_FillRect"); if (w <= 0 || h <= 0) { return; } RETURN_IF_NULL(oglc); CHECK_PREVIOUS_OP(GL_QUADS); GLRECT_BODY_XYWH(x, y, w, h); }
/* * Class: sun_java2d_windows_GDIRenderer * Method: doDrawArc * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_windows_GDIRenderer_doDrawArc (JNIEnv *env, jobject wr, jobject sData, jobject clip, jobject comp, jint color, jint x, jint y, jint w, jint h, jint angleStart, jint angleExtent) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawArc"); J2dTraceLn5(J2D_TRACE_VERBOSE, " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", color, x, y, w, h); J2dTraceLn2(J2D_TRACE_VERBOSE, " angleStart=%-4d angleExtent=%-4d", angleStart, angleExtent); if (w < 0 || h < 0 || angleExtent == 0) { return; } GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData); if (wsdo == NULL) { return; } long sx, sy, ex, ey; if (angleExtent >= 360 || angleExtent <= -360) { sx = ex = x + w; sy = ey = y + h/2; } else { int angleEnd; if (angleExtent < 0) { angleEnd = angleStart; angleStart += angleExtent; } else { angleEnd = angleStart + angleExtent; } AngleToCoord(angleStart, w, h, &sx, &sy); sx += x + w/2; sy += y + h/2; AngleToCoord(angleEnd, w, h, &ex, &ey); ex += x + w/2; ey += y + h/2; } HDC hdc = wsdo->GetDC(env, wsdo, PEN, NULL, clip, comp, color); if (hdc == NULL) { return; } ::Arc(hdc, x, y, x+w+1, y+h+1, sx, sy, ex, ey); wsdo->ReleaseDC(env, wsdo, hdc); }
JNIEXPORT void JNICALL Java_sun_java2d_opengl_OGLTextRenderer_drawGlyphList (JNIEnv *env, jobject self, jint numGlyphs, jboolean usePositions, jboolean subPixPos, jboolean rgbOrder, jint lcdContrast, jfloat glyphListOrigX, jfloat glyphListOrigY, jlongArray imgArray, jfloatArray posArray) { unsigned char *images; J2dTraceLn(J2D_TRACE_INFO, "OGLTextRenderer_drawGlyphList"); images = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, imgArray, NULL); if (images != NULL) { OGLContext *oglc = OGLRenderQueue_GetCurrentContext(); OGLSDOps *dstOps = OGLRenderQueue_GetCurrentDestination(); if (usePositions) { unsigned char *positions = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, posArray, NULL); if (positions != NULL) { OGLTR_DrawGlyphList(env, oglc, dstOps, numGlyphs, usePositions, subPixPos, rgbOrder, lcdContrast, glyphListOrigX, glyphListOrigY, images, positions); (*env)->ReleasePrimitiveArrayCritical(env, posArray, positions, JNI_ABORT); } } else { OGLTR_DrawGlyphList(env, oglc, dstOps, numGlyphs, usePositions, subPixPos, rgbOrder, lcdContrast, glyphListOrigX, glyphListOrigY, images, NULL); } // 6358147: reset current state, and ensure rendering is // flushed to dest if (oglc != NULL) { RESET_PREVIOUS_OP(); j2d_glFlush(); } (*env)->ReleasePrimitiveArrayCritical(env, imgArray, images, JNI_ABORT); } }
HRESULT D3DResourceManager::CreateInstance(D3DContext *pCtx, D3DResourceManager** ppResourceMgr) { HRESULT res; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::CreateInstance"); *ppResourceMgr = new D3DResourceManager(); if (FAILED(res = (*ppResourceMgr)->Init(pCtx))) { delete *ppResourceMgr; *ppResourceMgr = NULL; } return res; }
/** * Decreases the reference count of the array. If the refCount goes to 0, * then there are no more references to the array and all of the * array elements, the array itself, and this object can be destroyed. * * Returns the number of references left after it was decremented. */ int Devices::Release() { J2dTraceLn(J2D_TRACE_INFO, "Devices::Release"); CriticalSection::Lock l(arrayLock); int refs = --refCount; J2dTraceLn1(J2D_TRACE_VERBOSE, " refCount=%d", refs); if (refs == 0) { J2dTraceLn(J2D_TRACE_VERBOSE, " disposing the array"); if (devices != NULL) { for (int i = 0; i < numDevices; ++i) { if (devices[i] != NULL) { delete devices[i]; devices[i] = NULL; } } free(devices); // null out data, can help with debugging devices = NULL; } // it's safe to delete the instance and only // then release the static lock delete this; // for safety return immediately after committing suicide // (note: can not reference refCount here!) return refs; } else if (refs < 0) { J2dTraceLn1(J2D_TRACE_ERROR, "Devices::Release: Negative ref count! refCount=%d", refs); } return refs; }
JNIEXPORT jlong JNICALL Java_sun_java2d_opengl_WGLGraphicsConfig_makeNativeSharedContextCurrent (JNIEnv *env, jobject wglsd, jlong pCtx) { OGLContext *oglc = (OGLContext *)jlong_to_ptr(pCtx); WGLCtxInfo *ctxinfo; J2dTraceLn(J2D_TRACE_INFO, "in WGLGraphicsConfig_makeNativeSharedContextCurrent"); if (oglc == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "shared context is null"); return 0L; } ctxinfo = (WGLCtxInfo *)oglc->ctxInfo; if (!j2d_wglMakeCurrent(sharedSurfaceDC, ctxinfo->context)) { J2dTraceLn(J2D_TRACE_ERROR, "could not make shared WGL context current"); return 0L; } return pCtx; }
/** * Returns JNI_TRUE if the given GL_VERSION string meets the minimum * requirements (>= 1.2); JNI_FALSE otherwise. */ jboolean OGLContext_IsVersionSupported(const unsigned char *versionstr) { J2dTraceLn(J2D_TRACE_INFO, "OGLContext_IsVersionSupported"); if (versionstr == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLContext_IsVersionSupported: version string is null"); return JNI_FALSE; } // note that this check allows for OpenGL 2.x return ((versionstr[0] == '1' && versionstr[2] >= '2') || (versionstr[0] >= '2')); }