void GuiBitmapCtrl::onRender(Point2I offset, const RectI &updateRect)
{
    GFXDEBUGEVENT_SCOPE_EX( GuiBitmapCtrl_onRender, ColorI::GREEN, avar("GuiBitmapCtrl: %s", mBitmapName.c_str()) );
   if (mTextureObject)
   {
      GFX->getDrawUtil()->clearBitmapModulation();
		if(mWrap)
		{
         // We manually draw each repeat because non power of two textures will 
         // not tile correctly when rendered with GFX->drawBitmapTile(). The non POT
         // bitmap will be padded by the hardware, and we'll see lots of slack
         // in the texture. So... lets do what we must: draw each repeat by itself:
 			GFXTextureObject* texture = mTextureObject;
			RectI srcRegion;
			RectI dstRegion;
			float xdone = ((float)getExtent().x/(float)texture->mBitmapSize.x)+1;
			float ydone = ((float)getExtent().y/(float)texture->mBitmapSize.y)+1;

			int xshift = mStartPoint.x%texture->mBitmapSize.x;
			int yshift = mStartPoint.y%texture->mBitmapSize.y;
			for(int y = 0; y < ydone; ++y)
				for(int x = 0; x < xdone; ++x)
				{
		 			srcRegion.set(0,0,texture->mBitmapSize.x,texture->mBitmapSize.y);
  					dstRegion.set( ((texture->mBitmapSize.x*x)+offset.x)-xshift,
								      ((texture->mBitmapSize.y*y)+offset.y)-yshift,
								      texture->mBitmapSize.x,
								      texture->mBitmapSize.y);
               GFX->getDrawUtil()->drawBitmapStretchSR(texture,dstRegion, srcRegion, GFXBitmapFlip_None, GFXTextureFilterLinear);
				}

		}
		else
      {
         RectI rect(offset, getExtent());
         GFX->getDrawUtil()->drawBitmapStretch(mTextureObject, rect, GFXBitmapFlip_None, GFXTextureFilterLinear, false);
      }
   }

   if (mProfile->mBorder || !mTextureObject)
   {
      RectI rect(offset.x, offset.y, getExtent().x, getExtent().y);
      GFX->getDrawUtil()->drawRect(rect, mProfile->mBorderColor);
   }

   renderChildControls(offset, updateRect);
}
void RenderFormatToken::process(SceneState *state, RenderPassStateBin *callingBin)
{
   switch(mFCState)
   {
   case FTSWaiting:
      {
         GFXDEBUGEVENT_SCOPE_EX(RFT_Waiting, ColorI::BLUE, avar("[%s Activate] (%s)", getName(), GFXStringTextureFormat[mColorFormat]));
         mFCState = FTSActive;

         mViewportRect = GFX->getViewport();

         // Update targets
         _updateTargets();

         // If we have a copy PostEffect then get the active backbuffer copy 
         // now before we swap the render targets.
         GFXTexHandle curBackBuffer;
         if(mCopyPostEffect.isValid())
            curBackBuffer = PFXMGR->getBackBufferTex();

         // Push target
         GFX->pushActiveRenderTarget();
         GFX->setActiveRenderTarget(mTargetChain[mTargetChainIdx]);

         // Set viewport
         GFX->setViewport(mViewportRect);

         // Clear
         GFX->clear(GFXClearTarget | GFXClearZBuffer | GFXClearStencil, gCanvasClearColor, 1.0f, 0);

         // Set active z target on render pass
         if(mTargetDepthStencilTexture[mTargetChainIdx].isValid())
         {
            if(callingBin->getParentManager()->getDepthTargetTexture() != GFXTextureTarget::sDefaultDepthStencil)
               mStoredPassZTarget = callingBin->getParentManager()->getDepthTargetTexture();
            else
               mStoredPassZTarget = NULL;

            callingBin->getParentManager()->setDepthTargetTexture(mTargetDepthStencilTexture[mTargetChainIdx]);
         }

         // Run the PostEffect which copies data into the new target.
         if ( mCopyPostEffect.isValid() )
            mCopyPostEffect->process( state, curBackBuffer, &mViewportRect );
      }
      break;

   case FTSActive:
      {
         GFXDEBUGEVENT_SCOPE_EX(RFT_Active, ColorI::BLUE, avar("[%s Deactivate]", getName()));
         mFCState = FTSComplete;

         // Pop target
         AssertFatal(GFX->getActiveRenderTarget() == mTargetChain[mTargetChainIdx], "Render target stack went wrong somewhere");
         mTargetChain[mTargetChainIdx]->resolve();
         GFX->popActiveRenderTarget();

         // This is the GFX viewport when we were first processed.
         GFX->setViewport(mViewportRect);

         // Restore active z-target
         if(mTargetDepthStencilTexture[mTargetChainIdx].isValid())
         {
            callingBin->getParentManager()->setDepthTargetTexture(mStoredPassZTarget.getPointer());
            mStoredPassZTarget = NULL;
         }

         // Run the PostEffect which copies data to the backbuffer
         if(mResolvePostEffect.isValid())
         {
		      // Need to create a texhandle here, since inOutTex gets assigned during process()
            GFXTexHandle inOutTex = mTargetColorTexture[mTargetChainIdx];
            mResolvePostEffect->process( state, inOutTex, &mViewportRect );
         }
      }
      break;

   case FTSComplete:
      AssertFatal(false, "process() called on a RenderFormatToken which was already complete.");
      // fall through
   case FTSDisabled:
      break;
   }
}
void GuiOffscreenCanvas::renderFrame(bool preRenderOnly, bool bufferSwap /* = true */)
{
   if (!mTargetDirty)
      return;
   
#ifdef TORQUE_ENABLE_GFXDEBUGEVENTS
   char buf[256];
   dSprintf(buf, sizeof(buf), "OffsceenCanvas %s", getName() ? getName() : getIdString());
   GFXDEBUGEVENT_SCOPE_EX(GuiOffscreenCanvas_renderFrame, ColorI::GREEN, buf);
#endif
   
   PROFILE_START(OffscreenCanvasPreRender);

#ifdef TORQUE_GFX_STATE_DEBUG
   GFX->getDebugStateManager()->startFrame();
#endif

   if (mTarget->getSize() != mTargetSize)
   {
      _setupTargets();
      mNamedTarget.setViewport( RectI( Point2I::Zero, mTargetSize ) );
   }

   // Make sure the root control is the size of the canvas.
   Point2I size = mTarget->getSize();

   if(size.x == 0 || size.y == 0)
   {
      PROFILE_END();
      return;
   }

   RectI screenRect(0, 0, size.x, size.y);

   maintainSizing();

   //preRender (recursive) all controls
   preRender();

   PROFILE_END();

   // Are we just doing pre-render?
   if(preRenderOnly)
   {
      return;
   }

   resetUpdateRegions();

   PROFILE_START(OffscreenCanvasRenderControls);

   GuiCursor *mouseCursor = NULL;
   bool cursorVisible = true;

   Point2I cursorPos((S32)mCursorPt.x, (S32)mCursorPt.y);
   mouseCursor = mDefaultCursor;

	mLastCursorEnabled = cursorVisible;
	mLastCursor = mouseCursor;
	mLastCursorPt = cursorPos;

   // Set active target
   GFX->pushActiveRenderTarget();
   GFX->setActiveRenderTarget(mTarget);

   // Clear the current viewport area
   GFX->setViewport( screenRect );
   GFX->clear( GFXClearTarget, ColorF(0,0,0,0), 1.0f, 0 );

   resetUpdateRegions();

	// Make sure we have a clean matrix state 
   // before we start rendering anything!   
   GFX->setWorldMatrix( MatrixF::Identity );
   GFX->setViewMatrix( MatrixF::Identity );
   GFX->setProjectionMatrix( MatrixF::Identity );
   
   RectI contentRect(Point2I(0,0), mTargetSize);
   {
      // Render active GUI Dialogs
      for(iterator i = begin(); i != end(); i++)
      {
         // Get the control
         GuiControl *contentCtrl = static_cast<GuiControl*>(*i);
         
         GFX->setClipRect( contentRect );
         GFX->setStateBlock(mDefaultGuiSB);
         
         contentCtrl->onRender(contentCtrl->getPosition(), contentRect);
      }

      // Fill Blue if no Dialogs
      if(this->size() == 0)
         GFX->clear( GFXClearTarget, ColorF(0,0,0,1), 1.0f, 0 );

      GFX->setClipRect( contentRect );

      // Draw cursor
      // 
      if (mCursorEnabled && mouseCursor && mShowCursor)
      {
         Point2I pos((S32)mCursorPt.x, (S32)mCursorPt.y);
         Point2I spot = mouseCursor->getHotSpot();

         pos -= spot;
         mouseCursor->render(pos);
      }

      GFX->getDrawUtil()->clearBitmapModulation();
   }

   mTarget->resolve();
   GFX->popActiveRenderTarget();

   PROFILE_END();

   // Keep track of the last time we rendered.
   mLastRenderMs = Platform::getRealMilliseconds();
   mTargetDirty = mDynamicTarget;

   onFrameRendered();
}