mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-06-26 14:38:30 +02:00
216 lines
7.8 KiB
ActionScript
216 lines
7.8 KiB
ActionScript
|
// =================================================================================================
|
||
|
//
|
||
|
// Starling Framework
|
||
|
// Copyright Gamua GmbH. All Rights Reserved.
|
||
|
//
|
||
|
// This program is free software. You can redistribute and/or modify it
|
||
|
// in accordance with the terms of the accompanying license agreement.
|
||
|
//
|
||
|
// =================================================================================================
|
||
|
|
||
|
package starling.filters
|
||
|
{
|
||
|
import flash.display3D.Context3DProfile;
|
||
|
import flash.geom.Matrix3D;
|
||
|
import flash.geom.Rectangle;
|
||
|
|
||
|
import starling.core.Starling;
|
||
|
import starling.core.starling_internal;
|
||
|
import starling.display.DisplayObject;
|
||
|
import starling.textures.SubTexture;
|
||
|
import starling.textures.Texture;
|
||
|
import starling.utils.MathUtil;
|
||
|
|
||
|
use namespace starling_internal;
|
||
|
|
||
|
/** @private
|
||
|
*
|
||
|
* This class manages texture creation, pooling and disposal of all textures
|
||
|
* during filter processing.
|
||
|
*/
|
||
|
internal class FilterHelper implements IFilterHelper
|
||
|
{
|
||
|
private var _width:Number;
|
||
|
private var _height:Number;
|
||
|
private var _nativeWidth:int;
|
||
|
private var _nativeHeight:int;
|
||
|
private var _pool:Vector.<Texture>;
|
||
|
private var _usePotTextures:Boolean;
|
||
|
private var _textureFormat:String;
|
||
|
private var _preferredScale:Number;
|
||
|
private var _scale:Number;
|
||
|
private var _sizeStep:int;
|
||
|
private var _numPasses:int;
|
||
|
private var _projectionMatrix:Matrix3D;
|
||
|
private var _renderTarget:Texture;
|
||
|
private var _targetBounds:Rectangle;
|
||
|
private var _target:DisplayObject;
|
||
|
|
||
|
// helpers
|
||
|
private var sRegion:Rectangle = new Rectangle();
|
||
|
|
||
|
/** Creates a new, empty instance. */
|
||
|
public function FilterHelper(textureFormat:String="bgra")
|
||
|
{
|
||
|
_usePotTextures = Starling.current.profile == Context3DProfile.BASELINE_CONSTRAINED;
|
||
|
_preferredScale = Starling.contentScaleFactor;
|
||
|
_textureFormat = textureFormat;
|
||
|
_sizeStep = 64; // must be POT!
|
||
|
_pool = new <Texture>[];
|
||
|
_projectionMatrix = new Matrix3D();
|
||
|
_targetBounds = new Rectangle();
|
||
|
|
||
|
setSize(_sizeStep, _sizeStep);
|
||
|
}
|
||
|
|
||
|
/** Purges the pool. */
|
||
|
public function dispose():void
|
||
|
{
|
||
|
purge();
|
||
|
}
|
||
|
|
||
|
/** Starts a new round of rendering. If <code>numPasses</code> is greater than zero, each
|
||
|
* <code>getTexture()</code> call will be counted as one pass; the final pass will then
|
||
|
* return <code>null</code> instead of a texture, to indicate that this pass should be
|
||
|
* rendered to the back buffer.
|
||
|
*/
|
||
|
public function start(numPasses:int, drawLastPassToBackBuffer:Boolean):void
|
||
|
{
|
||
|
_numPasses = drawLastPassToBackBuffer ? numPasses : -1;
|
||
|
}
|
||
|
|
||
|
/** @inheritDoc */
|
||
|
public function getTexture(resolution:Number=1.0):Texture
|
||
|
{
|
||
|
var texture:Texture;
|
||
|
var subTexture:SubTexture;
|
||
|
|
||
|
if (_numPasses >= 0)
|
||
|
if (_numPasses-- == 0) return null;
|
||
|
|
||
|
if (_pool.length)
|
||
|
texture = _pool.pop();
|
||
|
else
|
||
|
texture = Texture.empty(_nativeWidth / _scale, _nativeHeight / _scale,
|
||
|
true, false, true, _scale, _textureFormat);
|
||
|
|
||
|
if (!MathUtil.isEquivalent(texture.width, _width, 0.1) ||
|
||
|
!MathUtil.isEquivalent(texture.height, _height, 0.1) ||
|
||
|
!MathUtil.isEquivalent(texture.scale, _scale * resolution))
|
||
|
{
|
||
|
sRegion.setTo(0, 0, _width * resolution, _height * resolution);
|
||
|
subTexture = texture as SubTexture;
|
||
|
|
||
|
if (subTexture)
|
||
|
subTexture.setTo(texture.root, sRegion, true, null, false, resolution);
|
||
|
else
|
||
|
texture = new SubTexture(texture.root, sRegion, true, null, false, resolution);
|
||
|
}
|
||
|
|
||
|
texture.root.clear();
|
||
|
return texture;
|
||
|
}
|
||
|
|
||
|
/** @inheritDoc */
|
||
|
public function putTexture(texture:Texture):void
|
||
|
{
|
||
|
if (texture)
|
||
|
{
|
||
|
if (texture.root.nativeWidth == _nativeWidth && texture.root.nativeHeight == _nativeHeight)
|
||
|
_pool.insertAt(_pool.length, texture);
|
||
|
else
|
||
|
texture.dispose();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** Purges the pool and disposes all textures. */
|
||
|
public function purge():void
|
||
|
{
|
||
|
for (var i:int = 0, len:int = _pool.length; i < len; ++i)
|
||
|
_pool[i].dispose();
|
||
|
|
||
|
_pool.length = 0;
|
||
|
}
|
||
|
|
||
|
/** Updates the size of the returned textures. Small size changes may allow the
|
||
|
* existing textures to be reused; big size changes will automatically dispose
|
||
|
* them. */
|
||
|
private function setSize(width:Number, height:Number):void
|
||
|
{
|
||
|
var factor:Number;
|
||
|
var newScale:Number = _preferredScale;
|
||
|
var maxNativeSize:int = Texture.maxSize;
|
||
|
var newNativeWidth:int = getNativeSize(width, newScale);
|
||
|
var newNativeHeight:int = getNativeSize(height, newScale);
|
||
|
|
||
|
if (newNativeWidth > maxNativeSize || newNativeHeight > maxNativeSize)
|
||
|
{
|
||
|
factor = maxNativeSize / Math.max(newNativeWidth, newNativeHeight);
|
||
|
newNativeWidth *= factor;
|
||
|
newNativeHeight *= factor;
|
||
|
newScale *= factor;
|
||
|
}
|
||
|
|
||
|
if (_nativeWidth != newNativeWidth || _nativeHeight != newNativeHeight ||
|
||
|
_scale != newScale)
|
||
|
{
|
||
|
purge();
|
||
|
|
||
|
_scale = newScale;
|
||
|
_nativeWidth = newNativeWidth;
|
||
|
_nativeHeight = newNativeHeight;
|
||
|
}
|
||
|
|
||
|
_width = width;
|
||
|
_height = height;
|
||
|
}
|
||
|
|
||
|
private function getNativeSize(size:Number, textureScale:Number):int
|
||
|
{
|
||
|
var nativeSize:Number = size * textureScale;
|
||
|
|
||
|
if (_usePotTextures)
|
||
|
return nativeSize > _sizeStep ? MathUtil.getNextPowerOfTwo(nativeSize) : _sizeStep;
|
||
|
else
|
||
|
return Math.ceil(nativeSize / _sizeStep) * _sizeStep;
|
||
|
}
|
||
|
|
||
|
/** The projection matrix that was active when the filter started processing. */
|
||
|
public function get projectionMatrix3D():Matrix3D { return _projectionMatrix; }
|
||
|
public function set projectionMatrix3D(value:Matrix3D):void
|
||
|
{
|
||
|
_projectionMatrix.copyFrom(value);
|
||
|
}
|
||
|
|
||
|
/** The render target that was active when the filter started processing. */
|
||
|
public function get renderTarget():Texture { return _renderTarget; }
|
||
|
public function set renderTarget(value:Texture):void
|
||
|
{
|
||
|
_renderTarget = value;
|
||
|
}
|
||
|
|
||
|
/** @inheritDoc */
|
||
|
public function get targetBounds():Rectangle { return _targetBounds; }
|
||
|
public function set targetBounds(value:Rectangle):void
|
||
|
{
|
||
|
_targetBounds.copyFrom(value);
|
||
|
setSize(value.width, value.height);
|
||
|
}
|
||
|
|
||
|
/** @inheritDoc */
|
||
|
public function get target():DisplayObject { return _target; }
|
||
|
public function set target(value:DisplayObject):void { _target = value; }
|
||
|
|
||
|
/** The scale factor of the returned textures. */
|
||
|
public function get textureScale():Number { return _preferredScale; }
|
||
|
public function set textureScale(value:Number):void
|
||
|
{
|
||
|
_preferredScale = value > 0 ? value : Starling.contentScaleFactor;
|
||
|
}
|
||
|
|
||
|
/** The texture format of the returned textures. @default BGRA */
|
||
|
public function get textureFormat():String { return _textureFormat; }
|
||
|
public function set textureFormat(value:String):void { _textureFormat = value; }
|
||
|
}
|
||
|
}
|