bool ConvertPixelDataDeferred( Interface *engineInterface, const pixelDataTraversal& srcPixels, pixelDataTraversal& dstPixels, const pixelFormat pixFormat ) { // First create a new copy of the texels. dstPixels.CloneFrom( engineInterface, srcPixels ); // Perform the conversion on the new texels. return ConvertPixelData( engineInterface, dstPixels, pixFormat ); }
bool ConvertPixelData( Interface *engineInterface, pixelDataTraversal& pixelsToConvert, const pixelFormat pixFormat ) { // We must have stand-alone pixel data. // Otherwise we could mess up pretty badly! assert( pixelsToConvert.isNewlyAllocated == true ); // Decide how to convert stuff. bool hasUpdated = false; eCompressionType srcCompressionType = pixelsToConvert.compressionType; eCompressionType dstCompressionType = pixFormat.compressionType; uint32 srcDXTType, dstDXTType; bool isSrcDXTCompressed = IsDXTCompressionType( srcCompressionType, srcDXTType ); bool isDstDXTCompressed = IsDXTCompressionType( dstCompressionType, dstDXTType ); bool shouldRecalculateAlpha = false; if ( isSrcDXTCompressed || isDstDXTCompressed ) { // Check whether the compression status even changed. if ( srcCompressionType != dstCompressionType ) { // If we were compressed, decompress. bool compressionSuccess = false; bool decompressionSuccess = false; if ( isSrcDXTCompressed ) { decompressionSuccess = genericDecompressDXTNative( engineInterface, pixelsToConvert, srcDXTType ); } else { // No decompression means we are always successful. decompressionSuccess = true; } if ( decompressionSuccess ) { // If we have to compress, do it. if ( isDstDXTCompressed ) { genericCompressDXTNative( engineInterface, pixelsToConvert, dstDXTType ); // No way to fail compression, yet. compressionSuccess = true; } else { // If we do not want to compress the target, then we // want to put it into a proper pixel format. pixelFormat pixSubFormat; pixSubFormat.rasterFormat = pixFormat.rasterFormat; pixSubFormat.depth = pixFormat.depth; pixSubFormat.colorOrder = pixFormat.colorOrder; pixSubFormat.paletteType = pixFormat.paletteType; pixSubFormat.compressionType = RWCOMPRESS_NONE; bool subSuccess = ConvertPixelData( engineInterface, pixelsToConvert, pixSubFormat ); // We are successful if the sub conversion succeeded. compressionSuccess = subSuccess; } } if ( compressionSuccess || decompressionSuccess ) { // TODO: if this routine is incomplete, revert to last known best status. hasUpdated = true; } } } else if ( srcCompressionType == RWCOMPRESS_NONE && dstCompressionType == RWCOMPRESS_NONE ) { ePaletteType srcPaletteType = pixelsToConvert.paletteType; ePaletteType dstPaletteType = pixFormat.paletteType; if ( srcPaletteType == PALETTE_NONE && dstPaletteType != PALETTE_NONE ) { // Call into the palettizer. // It will do the remainder of the complex job. PalettizePixelData( engineInterface, pixelsToConvert, pixFormat ); // We assume the palettization has always succeeded. hasUpdated = true; // Recalculating alpha is important. shouldRecalculateAlpha = true; } else if ( srcPaletteType != PALETTE_NONE && dstPaletteType == PALETTE_NONE || srcPaletteType != PALETTE_NONE && dstPaletteType != PALETTE_NONE || srcPaletteType == PALETTE_NONE && dstPaletteType == PALETTE_NONE ) { // Grab the values on the stack. eRasterFormat srcRasterFormat = pixelsToConvert.rasterFormat; eColorOrdering srcColorOrder = pixelsToConvert.colorOrder; uint32 srcDepth = pixelsToConvert.depth; eRasterFormat dstRasterFormat = pixFormat.rasterFormat; eColorOrdering dstColorOrder = pixFormat.colorOrder; uint32 dstDepth = pixFormat.depth; // Check whether we even have to update the texels. if ( srcRasterFormat != dstRasterFormat || srcPaletteType != dstPaletteType || srcColorOrder != dstColorOrder || srcDepth != dstDepth ) { // Grab palette parameters. void *srcPaletteTexels = pixelsToConvert.paletteData; uint32 srcPaletteSize = pixelsToConvert.paletteSize; uint32 srcPalRasterDepth; if ( srcPaletteType != PALETTE_NONE ) { srcPalRasterDepth = Bitmap::getRasterFormatDepth( srcRasterFormat ); } void *dstPaletteTexels = srcPaletteTexels; uint32 dstPaletteSize = srcPaletteSize; uint32 dstPalRasterDepth; if ( dstPaletteType != PALETTE_NONE ) { dstPalRasterDepth = Bitmap::getRasterFormatDepth( dstRasterFormat ); } // Check whether we have to update the palette texels. if ( dstPaletteType != PALETTE_NONE ) { // Make sure we had a palette before. assert( srcPaletteType != PALETTE_NONE ); if ( dstPaletteType == PALETTE_4BIT ) { dstPaletteSize = 16; } else if ( dstPaletteType == PALETTE_8BIT ) { dstPaletteSize = 256; } else { assert( 0 ); } // If the palette increased in size, allocate a new array for it. if ( srcPaletteSize != dstPaletteSize || srcPalRasterDepth != dstPalRasterDepth ) { uint32 dstPalDataSize = getRasterDataSize( dstPaletteSize, dstPalRasterDepth ); dstPaletteTexels = engineInterface->PixelAllocate( dstPalDataSize ); } } else { dstPaletteTexels = NULL; dstPaletteSize = 0; } // If we have a palette, process it. if ( srcPaletteType != PALETTE_NONE && dstPaletteType != PALETTE_NONE ) { ConvertPaletteData( srcPaletteTexels, dstPaletteTexels, srcPaletteSize, dstPaletteSize, srcRasterFormat, srcColorOrder, srcDepth, dstRasterFormat, dstColorOrder, dstDepth ); } // Process mipmaps. uint32 mipmapCount = pixelsToConvert.mipmaps.size(); // Determine the depth of the items. for ( uint32 n = 0; n < mipmapCount; n++ ) { pixelDataTraversal::mipmapResource& mipLayer = pixelsToConvert.mipmaps[ n ]; void *dstTexels; uint32 dstTexelsDataSize; // Convert this mipmap. ConvertMipmapLayer( engineInterface, mipLayer, srcRasterFormat, srcDepth, srcColorOrder, srcPaletteType, srcPaletteTexels, srcPaletteSize, dstRasterFormat, dstDepth, dstColorOrder, dstPaletteType, false, dstTexels, dstTexelsDataSize ); // Update mipmap properties. void *srcTexels = mipLayer.texels; if ( dstTexels != srcTexels ) { // Delete old texels. // We always have texels allocated. engineInterface->PixelFree( srcTexels ); // Replace stuff. mipLayer.texels = dstTexels; } uint32 srcTexelsDataSize = mipLayer.dataSize; if ( dstTexelsDataSize != srcTexelsDataSize ) { // Update the data size. mipLayer.dataSize = dstTexelsDataSize; } } // Update the palette if necessary. if ( srcPaletteTexels != dstPaletteTexels ) { if ( srcPaletteTexels ) { // Delete old palette texels. engineInterface->PixelFree( srcPaletteTexels ); } // Put in the new ones. pixelsToConvert.paletteData = dstPaletteTexels; } if ( srcPaletteSize != dstPaletteSize ) { pixelsToConvert.paletteSize = dstPaletteSize; } // Update the D3DFORMAT field. hasUpdated = true; // We definately should recalculate alpha. shouldRecalculateAlpha = true; } // Update texture properties that changed. if ( srcRasterFormat != dstRasterFormat ) { pixelsToConvert.rasterFormat = dstRasterFormat; } if ( srcPaletteType != dstPaletteType ) { pixelsToConvert.paletteType = dstPaletteType; } if ( srcColorOrder != dstColorOrder ) { pixelsToConvert.colorOrder = dstColorOrder; } if ( srcDepth != dstDepth ) { pixelsToConvert.depth = dstDepth; } } } // If we have updated the pixels, we _should_ recalculate the pixel alpha flag. if ( hasUpdated ) { if ( shouldRecalculateAlpha ) { pixelsToConvert.hasAlpha = calculateHasAlpha( pixelsToConvert ); } } return hasUpdated; }
static AINLINE void CompressNativeTexture( Interface *engineInterface, texNativeTypeProvider *texProvider, PlatformTexture *platformTex, eCompressionType targetCompressionType ) { // Since we now know about everything, we can take the pixels and perform the compression. pixelDataTraversal pixelData; texProvider->GetPixelDataFromTexture( engineInterface, platformTex, pixelData ); bool hasDirectlyAcquired = false; try { // Unset the pixels from the texture and make them standalone. texProvider->UnsetPixelDataFromTexture( engineInterface, platformTex, pixelData.isNewlyAllocated == true ); pixelData.SetStandalone(); // Compress things. pixelFormat targetPixelFormat; targetPixelFormat.rasterFormat = pixelData.rasterFormat; targetPixelFormat.depth = pixelData.depth; targetPixelFormat.rowAlignment = 0; targetPixelFormat.colorOrder = pixelData.colorOrder; targetPixelFormat.paletteType = PALETTE_NONE; targetPixelFormat.compressionType = targetCompressionType; bool hasCompressed = ConvertPixelData( engineInterface, pixelData, targetPixelFormat ); if ( !hasCompressed ) { throw RwException( "failed to compress raster" ); } AdjustPixelDataDimensionsByFormat( engineInterface, texProvider, pixelData ); // Put the new pixels into the texture. texNativeTypeProvider::acquireFeedback_t acquireFeedback; texProvider->SetPixelDataToTexture( engineInterface, platformTex, pixelData, acquireFeedback ); hasDirectlyAcquired = acquireFeedback.hasDirectlyAcquired; } catch( ... ) { pixelData.FreePixels( engineInterface ); throw; } if ( hasDirectlyAcquired == false ) { // Should never happen. pixelData.FreePixels( engineInterface ); } else { pixelData.DetachPixels(); } }