public final void doAccumulate(final float value) {
    // TOMD - scissoring

    //    int x0 = gc.transform.clipX0;
    //    int x1 = gc.transform.clipX1;
    //    int y0 = gc.transform.clipY0;
    //    int y1 = gc.transform.clipY1;

    final int width = gc.frameBuffer.width;

    final int x0 = gc.state.viewport.x;
    final int x1 = gc.state.viewport.width;
    final int y0 = gc.state.viewport.y * width;
    final int y1 = gc.state.viewport.height * width;

    final int[] cfb = gc.frameBuffer.readBuffer.buffer;
    final int[] localBuffer = buffer;

    final boolean scale = value != 1.0f;

    for (int x = x0, index; x < x1; ++x) {
      for (int y = y0; y < y1; y += width) {
        index = x + y;

        // GL_ACCUM Obtains R, G, B, and A values from the buffer currently selected for
        // reading (see glReadBuffer). Each component value is divided by 2^n– 1,
        // where n is the number of bits allocated to each color component in the currently
        // selected buffer. The result is a floating-point value in the range [0,1],
        // which is multiplied by value and added to the corresponding pixel component in
        // the accumulation buffer, thereby updating the accumulation buffer.

        c1.set(cfb[index]);

        // scale
        if (scale) {
          c1.r *= value;
          c1.g *= value;
          c1.b *= value;
          c1.a *= value;
        }

        c2.set(localBuffer[index]);

        // accumulate
        c2.r += c1.r;
        c2.g += c1.g;
        c2.b += c1.b;
        c2.a += c1.a;

        localBuffer[index] = c2.getRGBAi();
      }
    }
  }
  public final void doReturn(final float value) {
    // TOMD - scissoring ?

    //    int x0 = gc.transform.clipX0;
    //    int x1 = gc.transform.clipX1;
    //    int y0 = gc.transform.clipY0;
    //    int y1 = gc.transform.clipY1;

    final int width = gc.frameBuffer.width;

    final int x0 = gc.state.viewport.x;
    final int x1 = gc.state.viewport.width;
    final int y0 = gc.state.viewport.y * width;
    final int y1 = gc.state.viewport.height * width;

    final int[] cfb = gc.frameBuffer.readBuffer.buffer;

    final boolean scale = value != 1.0f;

    for (int x = x0, index; x < x1; ++x) {
      for (int y = y0; y < y1; y += width) {
        index = x + y;

        // GL_RETURN  Transfers accumulation buffer values to the color buffer or buffers
        // currently selected for writing. Each R, G, B, and A component is multiplied by value,
        // then multiplied by 2n– 1, clamped to the range [0, 2n – 1 ], and stored in the
        // corresponding display buffer cell. The only fragment operations that are applied to
        // this transfer are pixel ownership, scissor, dithering, and color writemasks.

        c1.set(buffer[index]);

        // scale
        if (scale) {
          c1.r *= value;
          c1.g *= value;
          c1.b *= value;
          c1.a *= value;
        }

        // clamp
        c1.r = c1.r < 0.0f ? 0.0f : (c1.r > 1.0f ? 1.0f : c1.r);
        c1.g = c1.g < 0.0f ? 0.0f : (c1.g > 1.0f ? 1.0f : c1.g);
        c1.b = c1.b < 0.0f ? 0.0f : (c1.b > 1.0f ? 1.0f : c1.b);
        c1.a = c1.a < 0.0f ? 0.0f : (c1.a > 1.0f ? 1.0f : c1.a);

        cfb[index] = c1.getRGBAi();
      }
    }
  }