anchor.diff:  
   (defmethod make-default-glstate-member ((name (eql 'glstate-front-face)))
     (make-instance 'gl-front-face))
  +
  +(defclass gl-framebuffers ()
  +  ((read-fbo :accessor read-fbo :initarg :read-fbo :initform nil)
  +   (draw-fbo :accessor draw-fbo :initarg :draw-fbo :initform nil)))
  +
  +(defmethod gl-finalize ((obj gl-framebuffers) &optional errorp)
  +  (let ((read-fbo (read-fbo obj))
  +        (draw-fbo (draw-fbo obj)))
  +    (when read-fbo
  +      (gl-finalize read-fbo errorp))
  +    (when draw-fbo
  +      (gl-finalize draw-fbo errorp))))
  +
  +(defmethod gl-finalized-p ((obj gl-framebuffers))
  +  (let ((read-fbo (read-fbo obj))
  +        (draw-fbo (draw-fbo obj)))
  +    (and (or (null read-fbo)
  +             (gl-finalized-p read-fbo))
  +         (or (null draw-fbo)
  +             (gl-finalized-p draw-fbo)))))
  +
  +(defmethod glstate-bind (tracker (element gl-framebuffers) previous)
  +  (declare (ignore tracker previous))
  +  (let ((read-fbo (read-fbo element))
  +        (draw-fbo (draw-fbo element)))
  +    (%gl:bind-framebuffer :read-framebuffer (if read-fbo
  +                                                (id read-fbo)
  +                                                0))
  +    (%gl:bind-framebuffer :draw-framebuffer (if draw-fbo
  +                                                (id draw-fbo)
  +                                                0))))
  +
  +(defmethod glstate-compare ((e1 gl-framebuffers) (e2 gl-framebuffers))
  +  (compare-object-pairs
  +   (read-fbo e1) (read-fbo e2)
  +   (draw-fbo e1) (draw-fbo e2)))
  +
  +(defmethod make-default-glstate-member ((name (eql 'glstate-framebuffers)))
  +  (make-instance 'gl-framebuffers))
  +
  +
  +(define-gl-object framebuffer-object ()
  +  ((color-attachments :accessor color-attachments :initarg :color-attachments :initform nil
  +                      :documentation "plist of attachment names and attachment specs. An attachment
  +spec is a texture or renderbuffer object, or a list of arguments for
  +@c(attach-framebuffer-texture)")
  +   (depth-attachment :accessor depth-attachment :initarg :depth-attachment :initform nil)
  +   (depth-stencil-attachment :accessor depth-stencil-attachment :initarg
  +                             :depth-stencil-attachment :initform nil)
  +   (gl-draw-buffers :accessor gl-draw-buffers :initarg :gl-draw-buffers
  +                    :initform '(:color-attachment0))))
  +
  +(defgeneric attach-framebuffer-texture (fb-target attachment-point texture &key level layer))
  +
  +(defmethod attach-framebuffer-texture (fb-target attachment-point (texture texture-2d)
  +                                       &key (level 0) layer)
  +  (declare (ignore layer))
  +  (gl:framebuffer-texture-2d fb-target attachment-point (target texture) (id texture) level))
  +
  +(defmethod gl-finalize ((obj framebuffer-object) &optional errorp)
  +  (flet ((get-attachment (tex)
  +           (if (listp tex)
  +               (car tex)
  +               tex))
  +         (attach (fb-target attachment attachment-spec)
  +           (if (listp attachment-spec)
  +               (apply #'attach-framebuffer-texture fb-target attachment attachment-spec)
  +               (attach-framebuffer-texture fb-target attachment attachment-spec))))
  +    (loop
  +       for tail on (color-attachments obj) by #'cddr
  +       for (nil color-attachment) = tail
  +       do (gl-finalize (get-attachment color-attachment) errorp))
  +    (when (depth-attachment obj)
  +      (gl-finalize (get-attachment (depth-attachment obj)) errorp))
  +    (when (depth-stencil-attachment obj)
  +      (gl-finalize (get-attachment (depth-stencil-attachment obj)) errorp)))
  +  (setf (id obj) (gl:gen-framebuffer))
  +  (gl:bind-framebuffer :framebuffer (id obj))
  +  (loop
  +     for tail on (color-attachments obj) by #'cddr
  +     for (attachment-point attachment) = tail
  +     do (attach :framebuffer attachment-point attachment))
  +  (when (depth-attachment obj)
  +    (attach-framebuffer-texture :framebuffer :depth-attachment  (depth-attachment obj)))
  +  (when (depth-stencil-attachment obj)
  +    (attach-framebuffer-texture
  +     :framebuffer :depth-stencil-attachment (depth-stencil-attachment obj)))
  +  (gl:draw-buffers (gl-draw-buffers obj))
  +  (gl:bind-framebuffer :framebuffer 0))
  +
   
   ;;; Graphics modes are the state controlled by gl:enable and gl:disable. They are represented as
   ;;; bits in an integer. The modes fit comfortably in a fixnum in 64 bit Lisps, but things are
  
positive.code:       :depth-func
        :depth-range
        :front-face
        #+nil :modes))
    (defparameter *glstate-elements*
      (let ((prefix (symbol-name '#:glstate-)))
        (mapcar (lambda (element)
  
negative.code:         (t
           (compare-num (id obj1) (id obj2)))))
  
  (defmacro compare-object-pairs (&rest pairs)
    "Call compare-gl-objects on each pair of arguments, but short-circuit and return the value if the
  result of the comparison is not 0."
    (if (null pairs)
        0
        (destructuring-bind (a b &rest rest-args)
            pairs
          (let ((result (gensym)))
            `(let ((,result (compare-gl-objects ,a ,b)))
               (if (zerop ,result)
                   (compare-gl-objects ,@rest-args)
                   ,result))))))
  
  (defmethod glstate-compare ((m1 gl-program) (m2 gl-program))
    (compare-gl-objects m1 m2))
  
  