/** * Returns JNI_TRUE if the given extension name is available for the current * GraphicsConfig; JNI_FALSE otherwise. An extension is considered available * if its identifier string is found amongst the space-delimited GL_EXTENSIONS * string. * * Adapted from the OpenGL Red Book, pg. 506. */ jboolean OGLContext_IsExtensionAvailable(const char *extString, char *extName) { jboolean ret = JNI_FALSE; char *p = (char *)extString; char *end; if (extString == NULL) { J2dTraceLn(J2D_TRACE_INFO, "OGLContext_IsExtensionAvailable"); J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLContext_IsExtensionAvailable: extension string is null"); return JNI_FALSE; } end = p + strlen(p); while (p < end) { size_t n = strcspn(p, " "); if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0)) { ret = JNI_TRUE; break; } p += (n + 1); } J2dRlsTraceLn2(J2D_TRACE_INFO, "OGLContext_IsExtensionAvailable: %s=%s", extName, ret ? "true" : "false"); return ret; }
// static HRESULT D3DPipelineManager::CheckForBadHardware(DWORD vId, DWORD dId, LONGLONG version) { DWORD vendorId, deviceId; UINT adapterInfo = 0; J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::CheckForBadHardware"); while ((vendorId = badHardware[adapterInfo].VendorId) != 0x0000 && (deviceId = badHardware[adapterInfo].DeviceId) != 0x0000) { if (vendorId == vId && (deviceId == dId || deviceId == ALL_DEVICEIDS)) { LONGLONG goodVersion = badHardware[adapterInfo].DriverVersion; USHORT osInfo = badHardware[adapterInfo].OsInfo; // the hardware check fails if: // - we have an entry for this OS and // - hardware is bad for all driver versions (NO_VERSION), or // we have a driver version which is older than the // minimum required for this OS if (D3DPPLM_OsVersionMatches(osInfo) && (goodVersion == NO_VERSION || version < goodVersion)) { J2dRlsTraceLn2(J2D_TRACE_ERROR, "D3DPPLM::CheckForBadHardware: found matching "\ "hardware: VendorId=0x%04x DeviceId=0x%04x", vendorId, deviceId); if (goodVersion != NO_VERSION) { // this was a match by the driver version LARGE_INTEGER li; li.QuadPart = goodVersion; J2dRlsTraceLn(J2D_TRACE_ERROR, " bad driver found, device disabled"); J2dRlsTraceLn4(J2D_TRACE_ERROR, " update your driver to at "\ "least version %d.%d.%d.%d", HIWORD(li.HighPart), LOWORD(li.HighPart), HIWORD(li.LowPart), LOWORD(li.LowPart)); } else { // this was a match by the device (no good driver for this // device) J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DPPLM::CheckForBadHardware: bad hardware "\ "found, device disabled"); } if (!bNoHwCheck) { return D3DERR_INVALIDDEVICE; } J2dRlsTraceLn(J2D_TRACE_WARNING, " Warning: hw/driver match "\ "overridden (via J2D_D3D_NO_HWCHECK)"); } } adapterInfo++; } return S_OK; }
/** * Returns the X11 VisualID that corresponds to the best GLXFBConfig for the * given screen. If no valid visual could be found, this method returns zero. * Note that this method will attempt to initialize GLX (and all the * necessary function symbols) if it has not been already. The AWT_LOCK * must be acquired before calling this method. */ VisualID GLXGC_FindBestVisual(JNIEnv *env, jint screen) { GLXFBConfig fbc; XVisualInfo *xvi; VisualID visualid; J2dRlsTraceLn1(J2D_TRACE_INFO, "GLXGC_FindBestVisual: scn=%d", screen); if (!GLXGC_IsGLXAvailable()) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXGC_FindBestVisual: could not initialize GLX"); return 0; } fbc = GLXGC_InitFBConfig(env, screen, 0); if (fbc == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXGC_FindBestVisual: could not find best visual"); return 0; } xvi = j2d_glXGetVisualFromFBConfig(awt_display, fbc); if (xvi == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXGC_FindBestVisual: could not get visual for fbconfig"); return 0; } visualid = xvi->visualid; XFree(xvi); J2dRlsTraceLn2(J2D_TRACE_INFO, "GLXGC_FindBestVisual: chose 0x%x as the best visual for screen %d", visualid, screen); return visualid; }
/** * Compiles and links the given fragment shader program. If * successful, this function returns a handle to the newly created shader * program; otherwise returns 0. */ GLhandleARB OGLContext_CreateFragmentProgram(const char *fragmentShaderSource) { GLhandleARB fragmentShader, fragmentProgram; GLint success; int infoLogLength = 0; J2dTraceLn(J2D_TRACE_INFO, "OGLContext_CreateFragmentProgram"); // create the shader object and compile the shader source code fragmentShader = j2d_glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); j2d_glShaderSourceARB(fragmentShader, 1, &fragmentShaderSource, NULL); j2d_glCompileShaderARB(fragmentShader); j2d_glGetObjectParameterivARB(fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &success); // print the compiler messages, if necessary j2d_glGetObjectParameterivARB(fragmentShader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infoLogLength); if (infoLogLength > 1) { char infoLog[1024]; j2d_glGetInfoLogARB(fragmentShader, 1024, NULL, infoLog); J2dRlsTraceLn2(J2D_TRACE_WARNING, "OGLContext_CreateFragmentProgram: compiler msg (%d):\n%s", infoLogLength, infoLog); } if (!success) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLContext_CreateFragmentProgram: error compiling shader"); j2d_glDeleteObjectARB(fragmentShader); return 0; } // create the program object and attach it to the shader fragmentProgram = j2d_glCreateProgramObjectARB(); j2d_glAttachObjectARB(fragmentProgram, fragmentShader); // it is now safe to delete the shader object j2d_glDeleteObjectARB(fragmentShader); // link the program j2d_glLinkProgramARB(fragmentProgram); j2d_glGetObjectParameterivARB(fragmentProgram, GL_OBJECT_LINK_STATUS_ARB, &success); // print the linker messages, if necessary j2d_glGetObjectParameterivARB(fragmentProgram, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infoLogLength); if (infoLogLength > 1) { char infoLog[1024]; j2d_glGetInfoLogARB(fragmentProgram, 1024, NULL, infoLog); J2dRlsTraceLn2(J2D_TRACE_WARNING, "OGLContext_CreateFragmentProgram: linker msg (%d):\n%s", infoLogLength, infoLog); } if (!success) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLContext_CreateFragmentProgram: error linking shader"); j2d_glDeleteObjectARB(fragmentProgram); return 0; } return fragmentProgram; }
HRESULT D3DPipelineManager::CheckAdaptersInfo() { D3DADAPTER_IDENTIFIER9 aid; UINT failedAdaptersCount = 0; J2dRlsTraceLn(J2D_TRACE_INFO, "CheckAdaptersInfo"); J2dRlsTraceLn(J2D_TRACE_INFO, "------------------"); for (UINT Adapter = 0; Adapter < adapterCount; Adapter++) { if (FAILED(pd3d9->GetAdapterIdentifier(Adapter, 0, &aid))) { pAdapters[Adapter].state = CONTEXT_INIT_FAILED; failedAdaptersCount++; continue; } J2dRlsTraceLn1(J2D_TRACE_INFO, "Adapter Ordinal : %d", Adapter); J2dRlsTraceLn1(J2D_TRACE_INFO, "Adapter Handle : 0x%x", pd3d9->GetAdapterMonitor(Adapter)); J2dRlsTraceLn1(J2D_TRACE_INFO, "Description : %s", aid.Description); J2dRlsTraceLn2(J2D_TRACE_INFO, "GDI Name, Driver : %s, %s", aid.DeviceName, aid.Driver); J2dRlsTraceLn1(J2D_TRACE_INFO, "Vendor Id : 0x%04x", aid.VendorId); J2dRlsTraceLn1(J2D_TRACE_INFO, "Device Id : 0x%04x", aid.DeviceId); J2dRlsTraceLn1(J2D_TRACE_INFO, "SubSys Id : 0x%x", aid.SubSysId); J2dRlsTraceLn4(J2D_TRACE_INFO, "Driver Version : %d.%d.%d.%d", HIWORD(aid.DriverVersion.HighPart), LOWORD(aid.DriverVersion.HighPart), HIWORD(aid.DriverVersion.LowPart), LOWORD(aid.DriverVersion.LowPart)); J2dRlsTrace3(J2D_TRACE_INFO, "[I] GUID : {%08X-%04X-%04X-", aid.DeviceIdentifier.Data1, aid.DeviceIdentifier.Data2, aid.DeviceIdentifier.Data3); J2dRlsTrace4(J2D_TRACE_INFO, "%02X%02X-%02X%02X", aid.DeviceIdentifier.Data4[0], aid.DeviceIdentifier.Data4[1], aid.DeviceIdentifier.Data4[2], aid.DeviceIdentifier.Data4[3]); J2dRlsTrace4(J2D_TRACE_INFO, "%02X%02X%02X%02X}\n", aid.DeviceIdentifier.Data4[4], aid.DeviceIdentifier.Data4[5], aid.DeviceIdentifier.Data4[6], aid.DeviceIdentifier.Data4[7]); if (FAILED(CheckForBadHardware(aid.VendorId, aid.DeviceId, aid.DriverVersion.QuadPart)) || FAILED(CheckDeviceCaps(Adapter)) || FAILED(D3DEnabledOnAdapter(Adapter))) { pAdapters[Adapter].state = CONTEXT_INIT_FAILED; failedAdaptersCount++; } J2dRlsTraceLn(J2D_TRACE_INFO, "------------------"); } if (failedAdaptersCount == adapterCount) { J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DPPLM::CheckAdaptersInfo: no suitable adapters found"); return E_FAIL; } return S_OK; }
JNIEXPORT jboolean JNICALL Java_sun_java2d_opengl_WGLSurfaceData_initPbuffer (JNIEnv *env, jobject wglsd, jlong pData, jlong pConfigInfo, jboolean isOpaque, jint width, jint height) { int attrKeys[] = { WGL_MAX_PBUFFER_WIDTH_ARB, WGL_MAX_PBUFFER_HEIGHT_ARB, }; int attrVals[2]; int pbAttrList[] = { 0 }; OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); WGLGraphicsConfigInfo *wglInfo = (WGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); WGLSDOps *wglsdo; HWND hwnd; HDC hdc, pbufferDC; HPBUFFERARB pbuffer; int maxWidth, maxHeight; int actualWidth, actualHeight; J2dTraceLn3(J2D_TRACE_INFO, "WGLSurfaceData_initPbuffer: w=%d h=%d opq=%d", width, height, isOpaque); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: ops are null"); return JNI_FALSE; } wglsdo = (WGLSDOps *)oglsdo->privOps; if (wglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: wgl ops are null"); return JNI_FALSE; } if (wglInfo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: wgl config info is null"); return JNI_FALSE; } // create a scratch window hwnd = WGLGC_CreateScratchWindow(wglInfo->screen); if (hwnd == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: could not create scratch window"); return JNI_FALSE; } // get the HDC for the scratch window hdc = GetDC(hwnd); if (hdc == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: could not get dc for scratch window"); DestroyWindow(hwnd); return JNI_FALSE; } // get the maximum allowable pbuffer dimensions j2d_wglGetPixelFormatAttribivARB(hdc, wglInfo->pixfmt, 0, 2, attrKeys, attrVals); maxWidth = attrVals[0]; maxHeight = attrVals[1]; J2dTraceLn4(J2D_TRACE_VERBOSE, " desired pbuffer dimensions: w=%d h=%d maxw=%d maxh=%d", width, height, maxWidth, maxHeight); // if either dimension is 0 or larger than the maximum, we cannot // allocate a pbuffer with the requested dimensions if (width == 0 || width > maxWidth || height == 0 || height > maxHeight) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: invalid dimensions"); ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); return JNI_FALSE; } pbuffer = j2d_wglCreatePbufferARB(hdc, wglInfo->pixfmt, width, height, pbAttrList); ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); if (pbuffer == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: could not create wgl pbuffer"); return JNI_FALSE; } // note that we get the DC for the pbuffer at creation time, and then // release the DC when the pbuffer is disposed; the WGL_ARB_pbuffer // spec is vague about such things, but from past experience we know // this approach to be more robust than, for example, doing a // Get/ReleasePbufferDC() everytime we make a context current pbufferDC = j2d_wglGetPbufferDCARB(pbuffer); if (pbufferDC == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: could not get dc for pbuffer"); j2d_wglDestroyPbufferARB(pbuffer); return JNI_FALSE; } // make sure the actual dimensions match those that we requested j2d_wglQueryPbufferARB(pbuffer, WGL_PBUFFER_WIDTH_ARB, &actualWidth); j2d_wglQueryPbufferARB(pbuffer, WGL_PBUFFER_HEIGHT_ARB, &actualHeight); if (width != actualWidth || height != actualHeight) { J2dRlsTraceLn2(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: actual (w=%d h=%d) != requested", actualWidth, actualHeight); j2d_wglReleasePbufferDCARB(pbuffer, pbufferDC); j2d_wglDestroyPbufferARB(pbuffer); return JNI_FALSE; } oglsdo->drawableType = OGLSD_PBUFFER; oglsdo->isOpaque = isOpaque; oglsdo->width = width; oglsdo->height = height; wglsdo->pbuffer = pbuffer; wglsdo->pbufferDC = pbufferDC; OGLSD_SetNativeDimensions(env, oglsdo, width, height); return JNI_TRUE; }
/** * Attempts to create a new GLXFBConfig for the requested screen and visual. * If visualid is 0, this method will iterate through all GLXFBConfigs (if * any) that match the requested attributes and will attempt to find an * fbconfig with a minimal combined depth+stencil buffer. Note that we * currently only need depth capabilities (for shape clipping purposes), but * glXChooseFBConfig() will often return a list of fbconfigs with the largest * depth buffer (and stencil) sizes at the top of the list. Therefore, we * scan through the whole list to find the most VRAM-efficient fbconfig. * If visualid is non-zero, the GLXFBConfig associated with the given visual * is chosen (assuming it meets the requested attributes). If there are no * valid GLXFBConfigs available, this method returns 0. */ static GLXFBConfig GLXGC_InitFBConfig(JNIEnv *env, jint screennum, VisualID visualid) { GLXFBConfig *fbconfigs; GLXFBConfig chosenConfig = 0; int nconfs, i; int attrlist[] = {GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PBUFFER_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_CONFIG_CAVEAT, GLX_NONE, // avoid "slow" configs GLX_DEPTH_SIZE, 16, // anything >= 16 will work for us 0}; // this is the initial minimum value for the combined depth+stencil size // (we initialize it to some absurdly high value; realistic values will // be much less than this number) int minDepthPlusStencil = 512; J2dRlsTraceLn2(J2D_TRACE_INFO, "GLXGC_InitFBConfig: scn=%d vis=0x%x", screennum, visualid); // find all fbconfigs for this screen with the provided attributes fbconfigs = j2d_glXChooseFBConfig(awt_display, screennum, attrlist, &nconfs); if ((fbconfigs == NULL) || (nconfs <= 0)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXGC_InitFBConfig: could not find any valid fbconfigs"); return 0; } J2dRlsTraceLn(J2D_TRACE_VERBOSE, " candidate fbconfigs:"); // iterate through the list of fbconfigs, looking for the one that matches // the requested VisualID and supports RGBA rendering as well as the // creation of windows and pbuffers for (i = 0; i < nconfs; i++) { XVisualInfo *xvi; VisualID fbvisualid; GLXFBConfig fbc = fbconfigs[i]; // get VisualID from GLXFBConfig xvi = j2d_glXGetVisualFromFBConfig(awt_display, fbc); if (xvi == NULL) { continue; } fbvisualid = xvi->visualid; XFree(xvi); if (visualid == 0 || visualid == fbvisualid) { int dtype, rtype, depth, stencil, db, alpha, gamma; // get GLX-specific attributes from GLXFBConfig j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_DRAWABLE_TYPE, &dtype); j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_RENDER_TYPE, &rtype); j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_DEPTH_SIZE, &depth); j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_STENCIL_SIZE, &stencil); // these attributes don't affect our decision, but they are // interesting for trace logs, so we will query them anyway j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_DOUBLEBUFFER, &db); j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_ALPHA_SIZE, &alpha); J2dRlsTrace5(J2D_TRACE_VERBOSE, "[V] id=0x%x db=%d alpha=%d depth=%d stencil=%d valid=", fbvisualid, db, alpha, depth, stencil); #ifdef __sparc /* * Sun's OpenGL implementation will always * return at least two GLXFBConfigs (visuals) from * glXChooseFBConfig(). The first will be a linear (gamma * corrected) visual; the second will have the same capabilities * as the first, except it will be a non-linear (non-gamma * corrected) visual, which is the one we want, otherwise * everything will look "washed out". So we will reject any * visuals that have gamma values other than 1.0 (the value * returned by glXGetFBConfigAttrib() will be scaled * by 100, so 100 corresponds to a gamma value of 1.0, 220 * corresponds to 2.2, and so on). */ j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_GAMMA_VALUE_SUN, &gamma); if (gamma != 100) { J2dRlsTrace(J2D_TRACE_VERBOSE, "false (linear visual)\n"); continue; } #endif /* __sparc */ if ((dtype & GLX_WINDOW_BIT) && (dtype & GLX_PBUFFER_BIT) && (rtype & GLX_RGBA_BIT) && (depth >= 16)) { if (visualid == 0) { // when visualid == 0, we loop through all configs // looking for an fbconfig that has the smallest combined // depth+stencil size (this keeps VRAM usage to a minimum) if ((depth + stencil) < minDepthPlusStencil) { J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n"); minDepthPlusStencil = depth + stencil; chosenConfig = fbc; } else { J2dRlsTrace(J2D_TRACE_VERBOSE, "false (large depth)\n"); } continue; } else { // in this case, visualid == fbvisualid, which means // we've found a valid fbconfig corresponding to the // requested VisualID, so break out of the loop J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n"); chosenConfig = fbc; break; } } else { J2dRlsTrace(J2D_TRACE_VERBOSE, "false (bad match)\n"); } } } // free the list of fbconfigs XFree(fbconfigs); if (chosenConfig == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXGC_InitFBConfig: could not find an appropriate fbconfig"); return 0; } return chosenConfig; }
/** * Initializes an OpenGL texture object. * * If the isOpaque parameter is JNI_FALSE, then the texture will have a * full alpha channel; otherwise, the texture will be opaque (this can * help save VRAM when translucency is not needed). * * If the GL_ARB_texture_non_power_of_two extension is present (texNonPow2 * is JNI_TRUE), the actual texture is allowed to have non-power-of-two * dimensions, and therefore width==textureWidth and height==textureHeight. * * Failing that, if the GL_ARB_texture_rectangle extension is present * (texRect is JNI_TRUE), the actual texture is allowed to have * non-power-of-two dimensions, except that instead of using the usual * GL_TEXTURE_2D target, we need to use the GL_TEXTURE_RECTANGLE_ARB target. * Note that the GL_REPEAT wrapping mode is not allowed with this target, * so if that mode is needed (e.g. as is the case in the TexturePaint code) * one should pass JNI_FALSE to avoid using this extension. Also note that * when the texture target is GL_TEXTURE_RECTANGLE_ARB, texture coordinates * must be specified in the range [0,width] and [0,height] rather than * [0,1] as is the case with the usual GL_TEXTURE_2D target (so take care)! * * Otherwise, the actual texture must have power-of-two dimensions, and * therefore the textureWidth and textureHeight will be the next * power-of-two greater than (or equal to) the requested width and height. */ static jboolean OGLSD_InitTextureObject(OGLSDOps *oglsdo, jboolean isOpaque, jboolean texNonPow2, jboolean texRect, jint width, jint height) { GLenum texTarget, texProxyTarget; GLint format = isOpaque ? GL_RGB : GL_RGBA; GLuint texID; GLsizei texWidth, texHeight, realWidth, realHeight; GLint texMax; J2dTraceLn4(J2D_TRACE_INFO, "OGLSD_InitTextureObject: w=%d h=%d opq=%d nonpow2=%d", width, height, isOpaque, texNonPow2); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitTextureObject: ops are null"); return JNI_FALSE; } if (texNonPow2) { // use non-pow2 dimensions with GL_TEXTURE_2D target j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texMax); texWidth = (width <= texMax) ? width : 0; texHeight = (height <= texMax) ? height : 0; texTarget = GL_TEXTURE_2D; texProxyTarget = GL_PROXY_TEXTURE_2D; } else if (texRect) { // use non-pow2 dimensions with GL_TEXTURE_RECTANGLE_ARB target j2d_glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &texMax); texWidth = (width <= texMax) ? width : 0; texHeight = (height <= texMax) ? height : 0; texTarget = GL_TEXTURE_RECTANGLE_ARB; texProxyTarget = GL_PROXY_TEXTURE_RECTANGLE_ARB; } else { // find the appropriate power-of-two dimensions j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texMax); texWidth = OGLSD_NextPowerOfTwo(width, texMax); texHeight = OGLSD_NextPowerOfTwo(height, texMax); texTarget = GL_TEXTURE_2D; texProxyTarget = GL_PROXY_TEXTURE_2D; } J2dTraceLn3(J2D_TRACE_VERBOSE, " desired texture dimensions: w=%d h=%d max=%d", texWidth, texHeight, texMax); // if either dimension is 0, we cannot allocate a texture with the // requested dimensions if ((texWidth == 0) || (texHeight == 0)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitTextureObject: texture dimensions too large"); return JNI_FALSE; } // now use a proxy to determine whether we can create a texture with // the calculated power-of-two dimensions and the given internal format j2d_glTexImage2D(texProxyTarget, 0, format, texWidth, texHeight, 0, format, GL_UNSIGNED_BYTE, NULL); j2d_glGetTexLevelParameteriv(texProxyTarget, 0, GL_TEXTURE_WIDTH, &realWidth); j2d_glGetTexLevelParameteriv(texProxyTarget, 0, GL_TEXTURE_HEIGHT, &realHeight); // if the requested dimensions and proxy dimensions don't match, // we shouldn't attempt to create the texture if ((realWidth != texWidth) || (realHeight != texHeight)) { J2dRlsTraceLn2(J2D_TRACE_ERROR, "OGLSD_InitTextureObject: actual (w=%d h=%d) != requested", realWidth, realHeight); return JNI_FALSE; } // initialize the texture with some dummy data (this allows us to create // a texture object once with 2^n dimensions, and then use // glTexSubImage2D() to provide further updates) j2d_glGenTextures(1, &texID); j2d_glBindTexture(texTarget, texID); j2d_glTexImage2D(texTarget, 0, format, texWidth, texHeight, 0, format, GL_UNSIGNED_BYTE, NULL); oglsdo->isOpaque = isOpaque; oglsdo->xOffset = 0; oglsdo->yOffset = 0; oglsdo->width = width; oglsdo->height = height; oglsdo->textureID = texID; oglsdo->textureWidth = texWidth; oglsdo->textureHeight = texHeight; oglsdo->textureTarget = texTarget; OGLSD_INIT_TEXTURE_FILTER(oglsdo, GL_NEAREST); OGLSD_RESET_TEXTURE_WRAP(texTarget); J2dTraceLn3(J2D_TRACE_VERBOSE, " created texture: w=%d h=%d id=%d", width, height, texID); return JNI_TRUE; }