static void Blit(
      SurfaceData srcData,
      SurfaceData dstData,
      Composite comp,
      Region clip,
      AffineTransform xform,
      int hint,
      int sx1,
      int sy1,
      int sx2,
      int sy2,
      double dx1,
      double dy1,
      double dx2,
      double dy2,
      int srctype,
      boolean texture) {
    int ctxflags = 0;
    if (srcData.getTransparency() == Transparency.OPAQUE) {
      ctxflags |= D3DContext.SRC_IS_OPAQUE;
    }

    D3DSurfaceData d3dDst = (D3DSurfaceData) dstData;
    D3DRenderQueue rq = D3DRenderQueue.getInstance();
    rq.lock();
    try {
      // make sure the RenderQueue keeps a hard reference to the
      // source (sysmem) SurfaceData to prevent it from being
      // disposed while the operation is processed on the QFT
      rq.addReference(srcData);

      if (texture) {
        // make sure we have a current context before uploading
        // the sysmem data to the texture object
        D3DContext.setScratchSurface(d3dDst.getContext());
      } else {
        D3DContext.validateContext(d3dDst, d3dDst, clip, comp, xform, null, null, ctxflags);
      }

      int packedParams = createPackedParams(false, texture, false, xform != null, hint, srctype);
      enqueueBlit(rq, srcData, dstData, packedParams, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);

      // always flush immediately, since we (currently) have no means
      // of tracking changes to the system memory surface
      rq.flushNow();
    } finally {
      rq.unlock();
    }

    if (d3dDst.getType() == D3DSurfaceData.WINDOW) {
      // flush immediately when copying to the screen to improve
      // responsiveness of applications using VI or BI backbuffers
      D3DScreenUpdateManager mgr = (D3DScreenUpdateManager) ScreenUpdateManager.getInstance();
      mgr.runUpdateNow();
    }
  }
  /**
   * Note: The srcImg and biop parameters are only used when invoked from the
   * D3DBufImgOps.renderImageWithOp() method; in all other cases, this method can be called with
   * null values for those two parameters, and they will be effectively ignored.
   */
  static void IsoBlit(
      SurfaceData srcData,
      SurfaceData dstData,
      BufferedImage srcImg,
      BufferedImageOp biop,
      Composite comp,
      Region clip,
      AffineTransform xform,
      int hint,
      int sx1,
      int sy1,
      int sx2,
      int sy2,
      double dx1,
      double dy1,
      double dx2,
      double dy2,
      boolean texture) {
    int ctxflags = 0;
    if (srcData.getTransparency() == Transparency.OPAQUE) {
      ctxflags |= D3DContext.SRC_IS_OPAQUE;
    }

    D3DSurfaceData d3dDst = (D3DSurfaceData) dstData;
    D3DRenderQueue rq = D3DRenderQueue.getInstance();
    boolean rtt = false;
    rq.lock();
    try {
      D3DSurfaceData d3dSrc = (D3DSurfaceData) srcData;
      int srctype = d3dSrc.getType();
      D3DSurfaceData srcCtxData = d3dSrc;
      if (srctype == D3DSurfaceData.TEXTURE) {
        rtt = false;
      } else {
        // the source is a backbuffer, or render-to-texture
        // surface; we set rtt to true to differentiate this kind
        // of surface from a regular texture object
        rtt = true;
      }

      D3DContext.validateContext(srcCtxData, d3dDst, clip, comp, xform, null, null, ctxflags);

      if (biop != null) {
        D3DBufImgOps.enableBufImgOp(rq, d3dSrc, srcImg, biop);
      }

      int packedParams = createPackedParams(true, texture, rtt, xform != null, hint, 0 /*unused*/);
      enqueueBlit(rq, srcData, dstData, packedParams, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);

      if (biop != null) {
        D3DBufImgOps.disableBufImgOp(rq, biop);
      }
    } finally {
      rq.unlock();
    }

    if (rtt && (d3dDst.getType() == D3DSurfaceData.WINDOW)) {
      // we only have to flush immediately when copying from a
      // (non-texture) surface to the screen; otherwise Swing apps
      // might appear unresponsive until the auto-flush completes
      D3DScreenUpdateManager mgr = (D3DScreenUpdateManager) ScreenUpdateManager.getInstance();
      mgr.runUpdateNow();
    }
  }