protected void allocate() {
    //System.out.println(this + " allocating for " + width + " " + height);
    //new Exception().printStackTrace();

    pixelCount = width * height;
    pixels = new int[pixelCount];
    zbuffer = new float[pixelCount];

    if (primarySurface) {
      cm = new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0x000000ff);;
      mis = new MemoryImageSource(width, height, pixels, 0, width);
      mis.setFullBufferUpdates(true);
      mis.setAnimated(true);
      image = Toolkit.getDefaultToolkit().createImage(mis);

    } else {
      // when not the main drawing surface, need to set the zbuffer,
      // because there's a possibility that background() will not be called
      Arrays.fill(zbuffer, Float.MAX_VALUE);
    }

    line = new PLine(this);
    triangle = new PTriangle(this);
    smoothTriangle = new PSmoothTriangle(this);
  }