United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4455041 : AWT code causes images in a Powerpoint doc to disappear

Details
Type:
Bug
Submit Date:
2001-05-06
Status:
Resolved
Updated Date:
2002-07-09
Project Name:
JDK
Resolved Date:
2002-04-04
Component:
client-libs
OS:
windows_2000
Sub-Component:
java.awt
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.3.0,1.4.1
Fixed Versions:
1.3.1_05 (05)

Related Reports
Backport:
Duplicate:

Sub Tasks

Description

Name: boT120536			Date: 05/06/2001


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

1. compile the following code:

import java.awt.*;

public class testawt3 extends java.awt.Frame {

    Image backImg;
    
    public testawt3() {
    }
    
    public void paint(Graphics g) {
	try {
	    Dimension dim = getSize();
	    
	    if (backImg == null) {
		backImg = createImage(dim.width, dim.height);
	    } else if ((backImg.getWidth(null) != dim.width) ||
		       (backImg.getHeight(null) != dim.height))
		{
		    backImg.flush();
		    backImg = createImage(dim.width, dim.height);
		}
     
	    if (backImg != null) {
	     	Graphics bg = backImg.getGraphics();
	     	try {
		    System.out.println("no super paint\n");
		    // super.paint(bg);

		    System.out.println("yes draw image\n");
	     	    g.drawImage(backImg, 0, 0, null);  // this is the line that
		    // is causing the problem
		    
		} finally {
		    bg.dispose();
		}
	    }
	         
	    return;
	} catch (Exception e) {
              // running on Solaris
              // sometimes Windows AWT throws NPE on drawImage()
          }
    }
    
    public static void main(String args[]) {
	System.out.println("testawt3\n");

	testawt3 test = new testawt3();
	test.show();
    }
}
 

2. Put these script in a batch file call testawt3.bat

REM -- This is for debugging only --
@set JDK12HOME=c:\\jdk1.3.1
%JDK12HOME%\jre\bin\java testawt3 %1% %2% %3% %4% %5% %6% %7% %8% %9%

3. Run this file as a Windows Service, to set it up follow the step

4. Get instsrv.exe and srvany.exe (part of the NT-resource kit)
5. Put srvany.exe in the txguardian directory
6. Run instsrv.exe like this:

instsrv testawt3 <testawt3-directory>\srvany.exe

4. Edit the registry, add a subkey called Parameters in

HKEY_Local_Machine\SYSTEM\CurrentControlSet\Services\testawt3

then create these string-values in that subkey

Application = c:\winnt\system32\cmd /k
AppParameters = <testawt3-directory>\testawt3.bat
AppDirectory = <testawt3-directory>

5. Start the testawt3 service, a console window should pop up
   then you will see the awt.frame pops up,

6. Resize the frame (that will causes the paint rountine in the testawt3 class
   to execute)

7. Open the Powerpoint document (you will see that some images on the top-right
   are missing)

8. Stop the testawt3 service, close the console window and the testawt3 frame

9. Open the Powerpoint document (you will see that those images that were
missing appears)

If I comment out the "drawImage" call in paint, then
the problem will go out, so I suspect that it is with the dramImage
method. This problem can be easily and consistenly reproduced.
Although sometimes, it will seems to work fine, but if
you reboot the machine then the problem can be reproduce
again consistenly.
(Review ID: 123743) 
======================================================================

Important note:
When installing the service as described above, it is important to change
the properties of the service as follows: In the "LogOn" tab of the properties
dialog for the service, check the "Allow service to interact with desktop".
This allows the program to actually run; without that option checked, the app
does not run and the problem is not apparent.

                                    

Comments
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
1.3.1_05
hopper

FIXED IN:
1.3.1_05
hopper

INTEGRATED IN:
1.3.1_05
hopper


                                     
2004-06-14
SUGGESTED FIX

------- Win32GraphicsDevice.java -------
*** /tmp/dfaayGa        Wed Mar 13 13:25:59 2002
--- Win32GraphicsDevice.java    Wed Mar  6 14:27:23 2002
***************
*** 52,57 ****
--- 52,58 ----
      private static boolean ddDisabled;
      private static boolean ddUsed;
      private static boolean ddInitialized;
+     private static boolean pfDisabled;
      private static AWTPermission fullScreenExclusivePermission;
  
      static {
***************
*** 59,64 ****
--- 60,74 ----
              new sun.security.action.GetPropertyAction("sun.java2d.noddraw"));
          ddDisabled = (noddraw != null && noddraw.length() > 0 &&
              noddraw.charAt(0) == 't');
+ 
+         // 4455041 - Even when ddraw is disabled, ddraw.dll is loaded when
+         // pixel format calls are made.  This causes problems when a Java app
+         // is run as an NT service.  To prevent the loading of ddraw.dll
+         // completely, sun.awt.nopixfmt should be set as well.  Apps which use
+         // OpenGL w/ Java probably don't want to set this.
+         String nopixfmt = (String)java.security.AccessController.doPrivileged(
+             new sun.security.action.GetPropertyAction("sun.awt.nopixfmt"));
+         pfDisabled = (nopixfmt != null);
        initIDs();
      }    
  
***************
*** 129,135 ****
              defaultPixID = getDefaultPixID(screen);
              Vector v = new Vector( max );
              if (defaultPixID == 0) {
!             //Workaround for failing GDI calls
                  defaultConfig = Win32GraphicsConfig.getConfig(this,
                   defaultPixID);
                  v.addElement(defaultConfig);
--- 139,145 ----
              defaultPixID = getDefaultPixID(screen);
              Vector v = new Vector( max );
              if (defaultPixID == 0) {
!             //Workaround for failing GDI calls, or if DirectDraw is disabled
                  defaultConfig = Win32GraphicsConfig.getConfig(this,
                   defaultPixID);
                  v.addElement(defaultConfig);
***************
*** 156,166 ****
      }
  
      /**
!      * Returns the maximum number of graphics configurations available.
       * This number is less than or equal to the number of graphics
       * configurations supported.
       */
!     protected native int getMaxConfigs(int screen);
  
      /**
       * Returns whether or not the PixelFormat indicated by index is 
--- 166,185 ----
      }
  
      /**
!      * Returns the maximum number of graphics configurations available, or 1
!      * if PixelFormat calls fail or are disabled.
       * This number is less than or equal to the number of graphics
       * configurations supported.
       */
!     protected int getMaxConfigs(int screen) {
!         if (pfDisabled) {
!             return 1;
!         } else {
!             return getMaxConfigsImpl(screen);
!         }
!     }
!   
!     private native int getMaxConfigsImpl(int screen);
  
      /**
       * Returns whether or not the PixelFormat indicated by index is 
***************
*** 168,173 ****
--- 187,194 ----
       * (PFD_DRAW_TO_WINDOW), support GDI (PFD_SUPPORT_GDI), and in the
       * case of an 8-bit format (cColorBits <= 8) uses indexed colors 
       * (iPixelType == PFD_TYPE_COLORINDEX).
+      * We use the index 0 to indicate that PixelFormat calls don't work, or
+      * are disabled.  Do not call this function with an index of 0.
       * @param index a PixelFormat index
       */
      protected native boolean isPixFmtSupported(int index, int screen);
***************
*** 174,182 ****
  
      /**
       * Returns the PixelFormatID of the default graphics configuration
!      * associated with this graphics device.
       */
!     protected native int getDefaultPixID(int screen);
      
      /**
       * Returns the default graphics configuration
--- 195,216 ----
  
      /**
       * Returns the PixelFormatID of the default graphics configuration
!      * associated with this graphics device, or 0 if PixelFormats calls fail or
!      * are disabled.
       */
!     protected int getDefaultPixID(int screen) {
!         if (pfDisabled) {
!             return 0;
!         } else {
!             return getDefaultPixIDImpl(screen);
!         }
!     }
! 
!     /**
!      * Returns the default PixelFormat ID from GDI.  Do not call if PixelFormats
!      * are disabled.
!      */
!     private native int getDefaultPixIDImpl(int screen);
      
      /**
       * Returns the default graphics configuration

------- awt_Win32GraphicsDevice.cpp -------
*** /tmp/dCcaiHa        Wed Mar 13 13:25:59 2002
--- awt_Win32GraphicsDevice.cpp Tue Mar 12 17:16:15 2002
***************
*** 734,744 ****
  
  /*
   * Class:     sun_awt_Win32GraphicsDevice
!  * Method:    getMaxConfigs
   * Signature: ()I
   */
  
! JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getMaxConfigs
      (JNIEnv* jniEnv, jobject theThis, jint screen) {
        TRY;
      HDC hDC = getDCFromScreen(screen);
--- 734,744 ----
  
  /*
   * Class:     sun_awt_Win32GraphicsDevice
!  * Method:    getMaxConfigsImpl
   * Signature: ()I
   */
  
! JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getMaxConfigsImpl
      (JNIEnv* jniEnv, jobject theThis, jint screen) {
        TRY;
      HDC hDC = getDCFromScreen(screen);
***************
*** 770,775 ****
--- 770,779 ----
        TRY;
      jboolean suppColor = JNI_TRUE;
      HDC hDC = getDCFromScreen(screen);
+ 
+     if (pixFmtID == 0) {
+         return true;
+     }
      
      PIXELFORMATDESCRIPTOR pfd;
      int max = ::DescribePixelFormat(hDC, (int)pixFmtID,
***************
*** 799,809 ****
  
  /*
   * Class:     sun_awt_Win32GraphicsDevice
!  * Method:    getDefaultPixID
!  * Signature: ()I
   */
  
! JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getDefaultPixID
      (JNIEnv* env, jobject theThis, jint screen) {
        TRY;
      int pixFmtID = 0;
--- 803,813 ----
  
  /*
   * Class:     sun_awt_Win32GraphicsDevice
!  * Method:    getDefaultPixIDImpl
!  * Signature: (I)I
   */
  
! JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getDefaultPixIDImpl
      (JNIEnv* env, jobject theThis, jint screen) {
        TRY;
      int pixFmtID = 0;
                                     
2004-06-11
WORK AROUND



Name: boT120536			Date: 05/06/2001


Doens't seem to have one.
======================================================================
                                     
2004-06-11
EVALUATION

Problems with rendering images are usually handled by 2D.  
eric.hawkes@eng 2001-05-06

It looks like there is a fundamental problem in win2k with loading ddraw
inside a Windows NT service.  I can take this problem completely outside
Java and demonstrate the problem as follows:
	- Here's a sample app that you can run as a service instead
	of the supplied Java app.  Follow the directions for the Java app,
	but use this as an executable instead:

		#include <windows.h>
		#include <stdio.h>
		void main(int argc, char **argv)
		{
		    ::LoadLibrary("ddraw.dll");
		    while (1) {
			printf("Sleeping\n");
			Sleep(1000);
		    }
		}
	(compile the app using msdev's cl compiler).

	- When starting the service, you should see a command console pop
	up and start printing "Sleeping" every second.

	- Now try to run any Java app at all.  Or, to make the problem even
	clearer, run a non-Java app that uses ddraw.  This includes the
	powerpoint app described.

	- See the resulting problems.  In the powerpoint doc, you should
	see missing images, as described.  If you run a ddraw app (such 
	as one of the sample apps from the sdk) you should see that it cannot
	run at all.

	- Stop the service and make sure that the service app is not
	running (you may need to kill that app in the Task Manager).

	- Run the ddraw app again and see that it functions normally.

This is obviously not a problem in Java, but is a fundamental flaw in the
way that WindowsNT interacts with ddraw.  Presumably there is a problem running
(or even loading) ddraw into the kernel and this is the root of the issue.

In any case, we can hardly fix this problem in Java.

We should be able to work around the problem.  The obvious workaround has
been tried: run java with -Dsun.java2d.noddraw=true.  This usually solves
ddraw-related problems.  However, it did not fix the problem in this case
because the problem comes not from what we are doing with ddraw but from
the act of simply loading the library.  the flag actually prevents us
from loading the library directly, but we issue a couple of calls related
to pixel formats which (on NT systems) load opengl32.dll; this, in turn,
loads ddraw.dll.

I believe the fix should be to prevent any opengl-related calls from being
issued if the noddraw flag has been set.  This will result in invalid pixel
format information, but we should be able to deal with that with some default
values.  But I need to validate this workaround/fix with the AWT team.

chet.haase@Eng 2001-08-09

Additional info: I reproduced the bug as described above on an ATI Rage Pro
Turbo video card, driver version 5.0.2195.4018.  When I tried the same test
on my Matrox G400 DualHead card instead, I could not reproduce the problem.
Could be a video card win2k driver problem instead of a Microsoft bug.

chet.haase@Eng 2001-08-09

More info: Microsoft admits this is a problem with DirectX (although they
thought it was not video-card specific), supposedly fixed in DX8.1.  We still
need to workaround the problem in our code, however, since we cannot affect
the version of DirectX installed on the user's system.

###@###.### 2001-09-13

There may be problems with Java3D if we sidestep PixelFormat calls when DirectDraw is disabled.
###@###.### 2001-09-20

I added a new flag, sun.awt.nopixfmt, which if set, prevent PixelFormat calls from being made.  I finally tracked down a machine which exhibited the bug, and this fixed the problem.
###@###.### 2002-03-13
                                     
2002-03-13



Hardware and Software, Engineered to Work Together