GFXTextureObject *GFXTextureManager::_createTexture(  GBitmap *bmp, 
                                                      const String &resourceName, 
                                                      GFXTextureProfile *profile, 
                                                      bool deleteBmp,
                                                      GFXTextureObject *inObj )
{
   PROFILE_SCOPE( GFXTextureManager_CreateTexture_Bitmap );
   
   #ifdef DEBUG_SPEW
   Platform::outputDebugString( "[GFXTextureManager] _createTexture (GBitmap) '%s'",
      resourceName.c_str()
   );
   #endif

   // Massage the bitmap based on any resize rules.
   U32 scalePower = getTextureDownscalePower( profile );

   GBitmap *realBmp = bmp;
   U32 realWidth = bmp->getWidth();
   U32 realHeight = bmp->getHeight();

   if (  scalePower && 
         isPow2(bmp->getWidth()) && 
         isPow2(bmp->getHeight()) && 
         profile->canDownscale() )
   {
      // We only work with power of 2 textures for now, so we 
      // don't have to worry about padding.

      // We downscale the bitmap on the CPU... this is the reason
      // you should be using DDS which already has good looking mips.
      GBitmap *padBmp = bmp;
      padBmp->extrudeMipLevels();
      scalePower = getMin( scalePower, padBmp->getNumMipLevels() - 1 );

      realWidth  = getMax( (U32)1, padBmp->getWidth() >> scalePower );
      realHeight = getMax( (U32)1, padBmp->getHeight() >> scalePower );
      realBmp = new GBitmap( realWidth, realHeight, false, bmp->getFormat() );

      // Copy to the new bitmap...
      dMemcpy( realBmp->getWritableBits(), 
               padBmp->getBits(scalePower),
               padBmp->getBytesPerPixel() * realWidth * realHeight );

      // This line is commented out because createPaddedBitmap is commented out.
      // If that line is added back in, this line should be added back in.
      // delete padBmp;
   }
void ScreenShot::capture( GuiCanvas *canvas )
{
   AssertFatal( mPending, "ScreenShot::capture() - The capture wasn't pending!" );

   if ( mTiles == 1 )
   {
      _singleCapture( canvas );
      return;
   }

   char filename[256];

   Point2I canvasSize = canvas->getPlatformWindow()->getVideoMode().resolution;
   
   // Calculate the real final size taking overlap in account
   Point2I overlapPixels( canvasSize.x * mPixelOverlap.x, canvasSize.y * mPixelOverlap.y );   

   // Calculate the overlap to be used by the frustum tiling, 
   // so it properly expands the frustum to overlap the amount of pixels we want
   mFrustumOverlap.x = ((F32)canvasSize.x/(canvasSize.x - overlapPixels.x*2)) * ((F32)overlapPixels.x/(F32)canvasSize.x);
   mFrustumOverlap.y = ((F32)canvasSize.y/(canvasSize.y - overlapPixels.y*2)) * ((F32)overlapPixels.y/(F32)canvasSize.y);
   
   //overlapPixels.set(0,0);
   // Get a buffer to write a row of tiles into.
   GBitmap *outBuffer = new GBitmap( canvasSize.x * mTiles - overlapPixels.x * mTiles * 2 , canvasSize.y - overlapPixels.y );

   // Open up the file on disk.
   dSprintf( filename, 256, "%s.%s", mFilename, "png" );
   FileStream fs;
   if ( !fs.open( filename, Torque::FS::File::Write ) )
      Con::errorf( "ScreenShot::capture() - Failed to open output file '%s'!", filename );

   // Open a PNG stream for the final image
   DeferredPNGWriter pngWriter;
   pngWriter.begin(outBuffer->getFormat(), outBuffer->getWidth(), canvasSize.y * mTiles - overlapPixels.y * mTiles * 2, fs, 0);
   
   // Render each tile to generate a huge screenshot.
   for( U32 ty=0; ty < mTiles; ty++ )
   {
      for( S32 tx=0; tx < mTiles; tx++ )
      {
         // Set the current tile offset for tileFrustum().
         mCurrTile.set( tx, mTiles - ty - 1 );

         // Let the canvas render the scene.
         canvas->renderFrame( false );

         // Now grab the current back buffer.
         GBitmap *gb = _captureBackBuffer();

			// The current GFX device couldn't capture the backbuffer or it's unable of doing so.
			if (gb == NULL)
				return;

                  
         // Copy the captured bitmap into its tile
         // within the output bitmap.         
         const U32 inStride = gb->getWidth() * gb->getBytesPerPixel();         
         const U8 *inColor = gb->getBits() + inStride * overlapPixels.y;
         const U32 outStride = outBuffer->getWidth() * outBuffer->getBytesPerPixel();
         const U32 inOverlapOffset = overlapPixels.x * gb->getBytesPerPixel();         
         const U32 inOverlapStride = overlapPixels.x * gb->getBytesPerPixel()*2;
         const U32 outOffset = (tx * (gb->getWidth() - overlapPixels.x*2 )) * gb->getBytesPerPixel();
         U8 *outColor = outBuffer->getWritableBits() + outOffset;
         for( U32 row=0; row < gb->getHeight() - overlapPixels.y; row++ )
         {
            dMemcpy( outColor, inColor + inOverlapOffset, inStride - inOverlapStride );
            
            //Grandient blend the left overlap area of this tile over the previous tile left border
            if (tx && !(ty && row < overlapPixels.y))
            {
               U8 *blendOverlapSrc = (U8*)inColor;
               U8 *blendOverlapDst = outColor - inOverlapOffset;
               for ( U32 px=0; px < overlapPixels.x; px++)
               {
                  F32 blendFactor = (F32)px / (F32)overlapPixels.x;
                  sBlendPixelRGB888(blendOverlapSrc, blendOverlapDst, blendFactor);                 

                  blendOverlapSrc += gb->getBytesPerPixel();
                  blendOverlapDst += outBuffer->getBytesPerPixel();                   
               }               
            }

            //Gradient blend against the rows the excess overlap rows already in the buffer            
            if (ty && row < overlapPixels.y)
            {
               F32 rowBlendFactor = (F32)row / (F32)overlapPixels.y;
               U8 *blendSrc = outColor + outStride * (outBuffer->getHeight() - overlapPixels.y);
               U8 *blendDst = outColor;               
               for ( U32 px=0; px < gb->getWidth() - overlapPixels.x*2; px++)
               {                  
                  sBlendPixelRGB888(blendSrc, blendDst, 1.0-rowBlendFactor); 
                  blendSrc += gb->getBytesPerPixel();
                  blendDst += outBuffer->getBytesPerPixel();                   
               }                              
            }

            
            inColor += inStride;
            outColor += outStride;
         }

         delete gb;
      }

      // Write the captured tile row into the PNG stream
      pngWriter.append(outBuffer, outBuffer->getHeight()-overlapPixels.y);
   }

   //Close the PNG stream
   pngWriter.end();
   
   // We captured... clear the flag.
   mPending = false;
}
Exemple #3
0
void ClipMap::fillWithTestPattern()
{
   AssertISV(false, "ClipMap::fillWithTestPattern - assumes bitmaps, which "
      "are no longer present, switch to lock() semantics if you need this!");

   // Table of random colors.
   U8 colorTbl[16][3] = 
   {
      { 0xFF, 0x00, 0x0F },
      { 0xFF, 0x00, 0xA0 },
      { 0xFF, 0x00, 0xFF },
      { 0x00, 0xA0, 0x00 },
      { 0x00, 0xA0, 0xAF },
      { 0x00, 0xA0, 0xF0 },
      { 0xA0, 0xFF, 0xA0 },
      { 0x00, 0xF0, 0xA0 },
      { 0x00, 0xF0, 0xFF },
      { 0xA0, 0x00, 0x00 },
      { 0xA0, 0x00, 0xAF },
      { 0xA0, 0x00, 0xF0 },
      { 0xA0, 0xF0, 0x0F },
      { 0xA0, 0xF0, 0xA0 },
      { 0xA0, 0xF0, 0xFF },
      { 0x00, 0xFF, 0x00 },
   };

   // Lock each layer of each texture and write a test pattern in.
   
   // Base levels first.
   for(S32 i=0; i<mClipStackDepth; i++)
   {
      GTexHandle &gth = mLevels[i].mTex;
      U8 *bmpData = (U8*)gth.getBitmap()->getWritableBits(0);

      for(S32 x=0; x<gth.getHeight(); x++)
      {
         for(S32 y=0; y<gth.getWidth(); y++)
         {
            S32 xFlag = x & 4;
            S32 yFlag = y & 4;

            U32 offset = (x * gth.getWidth() + y) * 4;
            if(xFlag ^ yFlag)
            {
               // Set bright.
               bmpData[offset+0] = colorTbl[i][0];
               bmpData[offset+1] = colorTbl[i][1];
               bmpData[offset+2] = colorTbl[i][2];
               bmpData[offset+3] = 0xFF;
            }
            else
            {
               // Set dim.
               bmpData[offset+0] = colorTbl[i][0] / 3;
               bmpData[offset+1] = colorTbl[i][1] / 3;
               bmpData[offset+2] = colorTbl[i][2] / 3;
               bmpData[offset+3] = 0xFF;
            }
         }
      }

      if(i == mClipStackDepth - 1)
         gth.getBitmap()->extrudeMipLevels();
      else
      {
         // Write black/translucent in the higher levels.
         GBitmap *gb = gth.getBitmap();
         for(S32 j=1; j<gb->getNumMipLevels(); j++)
         {
            U8 *b = gb->getWritableBits(j);
            dMemset(b, 0, 4 * gb->getWidth(j) * gb->getHeight(j));
         }
      }

      gth.refresh();
   }
}