JDK-4652373 : REGRESSION: InternalError in sun.java2d.loops.MaskFill when unlocking computer
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.4.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2002-03-13
  • Updated: 2003-04-12
  • Resolved: 2002-09-16
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
1.4.2 mantisFixed

Name: gm110360			Date: 03/13/2002

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

Microsoft Windows 2000 [Version 5.00.2195]
Service Pack 2

Computer: HP Omnibook 6000 Laptop
Videocard: ATI RAGE MOBILITY-M AGP (1600*1200@24bits)

have also seen this problem on other hw configurations.

When unlocking the computer an internal error occurs in
sun.java2d.loops.MaskFill.makePrimitive when painting with
a GradientPaint object.

1. Run a program containing the code.
2. Lock the workstation (press ctrl-alt-del, and
select 'Lock Computer')
3. Unlock workstation.
4. Component fails to paint and stack trace is visible.

The program prints out this before the stacktrace happens:
java.awt.Rectangle[x=0,y=0,width=500,height=500] w:500 h:500
java.awt.Rectangle[x=0,y=0,width=500,height=500] w:500 h:500

On my system this produces a stacktrace most of the time.

I expect this to throw no exceptions and paint normally.

java.lang.InternalError: MaskFill can only fill with colors
	at sun.java2d.loops.MaskFill.makePrimitive(MaskFill.java:120)
	at sun.java2d.loops.GraphicsPrimitiveMgr.locate
	at sun.java2d.loops.MaskFill.locate(MaskFill.java:46)
	at sun.java2d.loops.FillRect$General.<init>(FillRect.java:83)
	at sun.java2d.loops.FillRect.makePrimitive(FillRect.java:72)
	at sun.java2d.loops.GraphicsPrimitiveMgr.locate
	at sun.java2d.loops.FillRect.locate(FillRect.java:38)
	at sun.java2d.SurfaceData.makeRenderLoops(SurfaceData.java:473)
	at sun.java2d.SurfaceData.getRenderLoops(SurfaceData.java:456)
	at sun.awt.image.BufImgSurfaceData.getRenderLoops
	at sun.java2d.SunGraphics2D.revalidateAll(SunGraphics2D.java:2123)
	at sun.java2d.SunGraphics2D.fillRect(SunGraphics2D.java:2103)
	at Bug.paintComponent(Bug.java:16)
	at javax.swing.JComponent.paint(JComponent.java:804)
	at javax.swing.JComponent.paintChildren(JComponent.java:643)
	at javax.swing.JComponent.paint(JComponent.java:813)
	at javax.swing.JComponent.paintChildren(JComponent.java:643)
	at javax.swing.JComponent.paint(JComponent.java:813)
	at javax.swing.JLayeredPane.paint(JLayeredPane.java:552)
	at javax.swing.JComponent.paintChildren(JComponent.java:643)
	at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4742)
	at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4688)
	at javax.swing.JComponent.paint(JComponent.java:794)
	at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
	at sun.awt.SunGraphicsCallback.runOneComponent
	at sun.awt.SunGraphicsCallback.runComponents
	at java.awt.Container.paint(Container.java:1123)
	at sun.awt.RepaintArea.paint(RepaintArea.java:180)
	at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:260)
	at java.awt.Component.dispatchEventImpl(Component.java:3586)
	at java.awt.Container.dispatchEventImpl(Container.java:1437)
	at java.awt.Window.dispatchEventImpl(Window.java:1566)
	at java.awt.Component.dispatchEvent(Component.java:3367)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:445)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy
	at java.awt.EventDispatchThread.pumpEventsForHierarchy
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:130)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:98)

This bug can be reproduced often.

---------- BEGIN SOURCE ----------

import javax.swing.*;
import java.awt.*;

public class Bug extends JComponent
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;

        Insets insets = getInsets();
        Rectangle rect = new Rectangle(insets.left, insets.top, getWidth() -
insets.right - insets.left, getHeight() - insets.top - insets.bottom);
        g2d.setPaint(new GradientPaint(rect.x, rect.y, Color.white,
rect.x+rect.width, rect.y, Color.black));

        System.out.println(rect + " w:" + getWidth() + " h:"+getHeight());

        g2d.fillRect(0, 0, getWidth(), getHeight());

    public static void main(String[] args)
        JFrame frame = new JFrame("bug");
        Bug bug = new Bug();
        bug.setPreferredSize(new Dimension(500, 500));

---------- END SOURCE ----------

Release Regression From : 1.3.1_02
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

(Review ID: 143160) 

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mantis mantis-b02 FIXED IN: mantis mantis-b02 INTEGRATED IN: mantis mantis-b02

EVALUATION This seems tied to ddraw problems because of the surface loss mechanism that kicks in after a ctl-alt-del operation (or any other occurrence that causes surface loss). However, it is actually a problem tied to pipeline validation that just happens to be triggered because surface loss causes revalidation. This can be verified by changing the code in SunGraphics2D slightly. In fillRect(), if you insert a call to revalidateAll() (which should be a valid, if unnecessary, operation), then you will get the same exact failure - only this way you get it without anything happening to the surface. It seems that we are not properly validating the pipelines based on current state. Without the change to SunGraphics2D.fillRect(), we validate the pipelines using some standard which does not go through BufImgSurfaceData.getRenderLoops(). But when we make the change to sg2d.fillRect(), we call BISD.getRenderLoops(), which detects (correctly) that the sg2d paint state is not SOLIDCOLOR, so it returns the renderloops from its superclass. This eventually percolates down to a call to makePrimitive in MaskFill with a non-opaque surface type (Paint Object), which MaskFill apparently cannot handle. Since this is not related to ddraw/win32, but is instead coming from a problem with pipeline validation, I'm forwarding the bug to Jim. ###@###.### 2002-03-15 It looks like the revalidateAll() code always tries to reconstruct the primitive operation loops (i.e. calls getRenderLoops which may or may not call makeRenderLoops). As it so happens, the primitive operation loops are only used during certain forms of basic rendering (i.e. not when GradientPaint is being used) and trying to construct loops under other conditions will fail. The pipeline validation code knows when to try to construct the list of primitive operation loops and when not to, but the code that revalidates a Graphics2D when the surface is reconfigured seems to always do it. The revalidateAll() code needs to be modified so that it only tries to reconstruct the loops when they are needed. Alternately, this code could simply call invalidate() and validate() to achieve the same effect with the proper protection against invalid loops. ###@###.### 2002-07-17