Generally its the lack of Z-buffer, meaning that everything is drawn using the "painters algorithm" that stipulates you have to draw every poly from back-to-front within the scene.
What this means in practice is every view has a distinct sequential draw-order that shifts according to the perspective its viewed from. You could automate this, but the most efficient method was to store (typically 8, using an octant principle) independent sort-lists per object, plus a global scene order that is calculated algorithmically.
Key issue is that using the painters algorithm, not every shape will work from every angle causing flickering as the code does its best to do things in the right order.
Additionally the lack of perspective-correct texturing in hardware meant that you had to use tesselation in order to prevent things become a blurry mess. i.e you would subdivide one poly into multiple smaller ones and adjust the UV (texture coord) values accordingly to spread the image out correctly. This process is lossy due to precision issues and again could cause jittering as the new UV's failed to match up perfectly.