United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 4833528 InternalException, "not yet implemented" thrown with CustomComposite
4833528 : InternalException, "not yet implemented" thrown with CustomComposite

Details
Type:
Bug
Submit Date:
2003-03-17
Status:
Open
Updated Date:
2008-05-16
Project Name:
JDK
Resolved Date:
Component:
client-libs
OS:
windows_nt,windows_xp
Sub-Component:
2d
CPU:
x86
Priority:
P4
Resolution:
Unresolved
Affected Versions:
1.4.0,1.4.1,1.4.2
Targeted Versions:

Related Reports

Sub Tasks

Description
Name: rmT116609			Date: 03/17/2003


FULL PRODUCT VERSION :
java version "1.4.1_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_02-b06)
Java HotSpot(TM) Client VM (build 1.4.1_02-b06, mixed mode)

FULL OS VERSION :
Microsoft Windows XP [Version 5.1.2600]

EXTRA RELEVANT SYSTEM CONFIGURATION :
ATI Rage Mobility 7200


A DESCRIPTION OF THE PROBLEM :
Exception dump:
java.lang.InternalError: not implemented yet
   at sun.awt.windows.Win32OffScreenSurfaceData.getRaster
   at sun.java2d.pipe.GeneralCompositePipe.renderPathTile
   at sun.java2d.pipe.TextRenderer.drawGlyphList
   at sun.java2d.pipe.GlyphListPipe.drawGlyphVector
   at sun.java2d.SunGraphics2D.drawGlyphVector

Our Code:


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the sample code as java -cp . Test

EXPECTED VERSUS ACTUAL BEHAVIOR :
The string should render without exception.
An exception is thrown, see Error Messages

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception dump:
java.lang.InternalError: not implemented yet
   at sun.awt.windows.Win32OffScreenSurfaceData.getRaster
   at sun.java2d.pipe.GeneralCompositePipe.renderPathTile
   at sun.java2d.pipe.TextRenderer.drawGlyphList
   at sun.java2d.pipe.GlyphListPipe.drawGlyphVector
   at sun.java2d.SunGraphics2D.drawGlyphVector


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.image.*;
import java.awt.font.*;
import java.awt.geom.*;
import javax.swing.*;

public class Test
{
   public static void main(String[] args)
   {
      TestPanel panel = new TestPanel();
      JDialog dialog = new JDialog();
      dialog.getContentPane().add(panel);
      dialog.setSize(400,400);
      dialog.setVisible(true);
   }
}

class TestPanel extends JPanel
{
   /** We override the paint method to handle all painting our selves */
   public void paint(Graphics p_graphics)
   {
      // Convert the passing graphics to the Graphics2D object that is must be
      Graphics2D g = (Graphics2D)p_graphics;
      
      // Get the size we are working with
      Dimension size = getSize();
      
      // Render the page
      g.setComposite(ORComposite.DEFAULT);

      String testString = "Testing String...";
      float x = 20;
      float advance = 0.10f;
      FontRenderContext frc = g.getFontRenderContext();
      Font font = g.getFont();
      char[] c = new char[1];
      for (int i = 0; i < testString.length(); i++)
      {
         c[0] = testString.charAt(i);
         GlyphVector gv = font.createGlyphVector(frc, c);
         g.drawGlyphVector(gv, x, 20);
         x += advance;
      }
   }
}

/** Returns the CompositeContext that will correctly
 * handle summing the source and destination pixels in a way that mirrors ink
 * being put down on a page. The standard composites could not support this
 * behavior since we are not working with semi-transparent color and using
 * the alpha channel was not going to work. */
class ORComposite implements Composite
{ 
   /** Only one of these is, so a static object is creatd. */
   public final static ORComposite DEFAULT = new ORComposite();
   
   /** Create the CompositeContext that will be used. It keeps no state, so
    * we really only need one of them. Since this class is a Singleton, there
    * will only be one instance of CompositContext created as only one
    * Composite is created */
   private final ORCompositeContext m_context = new ORCompositeContext();
   
   /** The class is a singleton, so the constuctor is hidden as a private. */
   private ORComposite()
   {
   }
  
   /** Return the composite the implements the ink paradigm */
   public CompositeContext createContext(ColorModel p_sCM, ColorModel p_dCM,
                                         RenderingHints p_hints)
   {
      return m_context;
   }

   /** Implements the idea of a composite that mirrors putting ink down on a
    * piece of paper. */
   class ORCompositeContext implements CompositeContext
   {
      /** There is state kept, so there is nothing to this function. */
      public void dispose()
      {
      }
  
      /** Do the work of composing the souce and the destination into the
       * output raster.
       * @see java.awt.CompositeContext#compose(Raster, Raster, WritableRaster)
       */
      public void compose(Raster p_srcIn, Raster p_dstIn,
                          WritableRaster p_dstOut)
      {
         // Walk the entire destination
         for (int x=0; x < p_dstOut.getWidth(); x++)
         {
            for (int y = 0; y < p_dstOut.getHeight(); y++)
            {
               //   Get the source pixels
               int[] src = new int[4];
               p_srcIn.getPixel(x, y, src);
            
               int[] dst = new int[4];
               p_dstIn.getPixel(x, y, dst);
             
               // Create a logaction for the result
               int[] result = new int[4];
            
               // OR the pixels together
               // We need to do the ^ 0xFFFFFF to invert the colors since the
               // screen sees 0xFFFFFF as white and 0x000000 as black, but we
               // want to sum up the underlying greyscales and make them
               // darker, as it would work with ink, so everything gets
               // inverted.
               result[0] = (src[0] ^ 0xFFFFFF) | (dst[0] ^ 0xFFFFFF);
               result[0] = result[0] ^ 0xFFFFFF;
               result[1] = (src[1] ^ 0xFFFFFF) | (dst[1] ^ 0xFFFFFF);
               result[1] = result[1] ^ 0xFFFFFF;
               result[2] = (src[2] ^ 0xFFFFFF) | (dst[2] ^ 0xFFFFFF);
               result[2] = result[2] ^ 0xFFFFFF;

               // Set the pixel with the values we have calulated
               p_dstOut.setPixel(x, y, result);
            }
         }
      }
   }
} 

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

CUSTOMER SUBMITTED WORKAROUND :
Passing in sun.java2d.noddraw=true flag will work, but this is completely
unacceptabel as a work around since we cannot expect out client base to
be using the Java Control Panel to set this value, and we cannot set the
value from the Object tag used to load the applet.
(Review ID: 182679) 
======================================================================
###@###.### 10/21/04 14:52 GMT

                                    

Comments
WORK AROUND

Perform custom composite operations on an image buffer instead of the
screen.  This workaround has several advantages:

- The performance will not be hindered by slow readback of screen
  pixels from most modern accelerated graphics cards.

- The correctness of the compositing algorithm will not depend on
  which mode the screen is in because the image buffer can be
  created with a known pixel format (by constructing a BufferedImage
  directly with a specified type).

- And lastly, this bug will not be encountered.
                                     
2004-06-11
EVALUATION

We currently don't have a way for our "SurfaceData" objects to supply the
Raster needed for a Java level algorithm to directly modify them.  We hope
to fix this in the not too distant future, but it is important to note the
caveats in the WorkAround field to realize that this bug fix may not be
the solution that everyone wants in the long run and that they are better
off moving to an offscreen buffer for their custom compositing operations
for practical reasons that go beyond simply avoiding this bug.

In particular, the supplied test case assumes a given pixel format in
its operations and will fail miserably if the screen is in 256 color
mode (producing random colors) or is a grayscale display.  If the
screen is in 16-bit color mode then the accuracy of the results will
be less than optimal and will accumulate errors more quickly than
operating on a 24 or 32-bit display.  These issues can be worked
around in the implementation of the custom composite, but such an
effort would be a major undertaking to ensure compatibility with
the many pixel formats that are possible to specify within our
system.

Further, the performance of reading the pixels back from the screen
for most modern graphics cards is horrible - much worse than most
developers might expect.  Todays graphics cards are heavily geared
towards a "write only" access model for the fastest possible gaming
performance.  I have little doubt that if we fixed this bug, the
first thing that an implementor of a custom composite would do with
the fixed runtime would be to switch to an offscreen image for
performance reasons unless performance was of very little concern
to them.  There is even talk of a new breed of cards under
development that will not have any capability to read pixels back
from the screen.  When running on any of those new cards we would
actually be prevented from satisfying this request by the hardware
we were running on.

Given the many positive features of the primary workaround of using
an offscreen image to do the custom compositing, we are not assigning
a very high priority to fixing this bug and recommending that developers
double buffer their custom composite operations.  This bug serves
more as a reminder that there is a theoretical hole in our implementation
than an identification of a practical loss for the developers.

###@###.### 2003-09-15
                                     
2003-09-15



Hardware and Software, Engineered to Work Together