2021-12-26 21:19:38 +01:00
/* ScummVM - Graphic Adventure Engine
2014-08-15 22:51:49 +02:00
*
2021-12-26 21:19:38 +01:00
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
2014-08-15 22:51:49 +02:00
* file distributed with this source distribution .
*
2021-12-26 18:47:58 +01:00
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
2014-08-15 22:51:49 +02:00
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2021-12-26 18:47:58 +01:00
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2014-08-15 22:51:49 +02:00
*
*/
2021-11-27 21:29:02 +01:00
# include "common/array.h"
2014-07-02 19:08:47 +02:00
# include "graphics/tinygl/zblit.h"
# include "graphics/tinygl/zgl.h"
2021-11-27 21:29:02 +01:00
# include "graphics/tinygl/pixelbuffer.h"
2014-08-07 17:54:53 +02:00
# include "graphics/tinygl/zdirtyrect.h"
2014-07-25 15:45:12 +02:00
# include "graphics/tinygl/gl.h"
2021-12-08 14:52:18 +01:00
2014-07-16 02:24:34 +02:00
# include <math.h>
2014-07-07 18:17:54 +02:00
2021-12-06 13:57:41 +01:00
namespace TinyGL {
2014-07-12 11:41:55 +02:00
2014-07-13 19:01:23 +02:00
Common : : Point transformPoint ( float x , float y , int rotation ) ;
Common : : Rect rotateRectangle ( int x , int y , int width , int height , int rotation , int originX , int originY ) ;
2014-07-13 18:49:27 +02:00
2014-07-07 21:14:58 +02:00
struct BlitImage {
2014-07-07 18:17:54 +02:00
public :
2016-07-28 23:32:43 +00:00
BlitImage ( ) : _isDisposed ( false ) , _version ( 0 ) , _binaryTransparent ( false ) , _refcount ( 1 ) { }
2014-07-07 18:17:54 +02:00
2014-07-07 21:14:58 +02:00
void loadData ( const Graphics : : Surface & surface , uint32 colorKey , bool applyColorKey ) {
2014-08-13 21:11:35 +02:00
const Graphics : : PixelFormat textureFormat ( 4 , 8 , 8 , 8 , 8 , 0 , 8 , 16 , 24 ) ;
2017-04-30 02:26:25 +00:00
int size = surface . w * surface . h ;
2014-07-07 18:17:54 +02:00
_surface . create ( surface . w , surface . h , textureFormat ) ;
2014-07-16 14:18:01 +02:00
Graphics : : PixelBuffer buffer ( surface . format , ( byte * ) const_cast < void * > ( surface . getPixels ( ) ) ) ;
2014-07-16 16:46:56 +02:00
Graphics : : PixelBuffer dataBuffer ( textureFormat , ( byte * ) const_cast < void * > ( _surface . getPixels ( ) ) ) ;
2017-04-30 02:26:25 +00:00
dataBuffer . copyBuffer ( 0 , 0 , size , buffer ) ;
2014-07-14 18:11:23 +02:00
if ( applyColorKey ) {
2017-04-30 02:26:25 +00:00
for ( int x = 0 ; x < size ; x + + ) {
if ( buffer . getValueAt ( x ) = = colorKey ) {
// Color keyed pixels become transparent white.
dataBuffer . setPixelAt ( x , 0 , 255 , 255 , 255 ) ;
2014-07-04 19:34:12 +02:00
}
}
2014-07-02 19:08:47 +02:00
}
2014-07-14 18:11:23 +02:00
2014-07-07 18:17:54 +02:00
// Create opaque lines data.
2014-07-13 16:17:17 +02:00
// A line of pixels can not wrap more that one line of the image, since it would break
// blitting of bitmaps with a non-zero x position.
Graphics : : PixelBuffer srcBuf = dataBuffer ;
_lines . clear ( ) ;
2014-07-17 13:22:15 +02:00
_binaryTransparent = true ;
2014-07-13 16:17:17 +02:00
for ( int y = 0 ; y < surface . h ; y + + ) {
int start = - 1 ;
for ( int x = 0 ; x < surface . w ; + + x ) {
// We found a transparent pixel, so save a line from 'start' to the pixel before this.
uint8 r , g , b , a ;
srcBuf . getARGBAt ( x , a , r , g , b ) ;
2014-07-17 13:22:15 +02:00
if ( a ! = 0 & & a ! = 0xFF ) {
_binaryTransparent = false ;
}
2014-07-13 16:17:17 +02:00
if ( a = = 0 & & start > = 0 ) {
2017-04-30 02:16:40 +00:00
_lines . push_back ( Line ( start , y , x - start , srcBuf . getRawBuffer ( start ) , textureFormat ) ) ;
2014-07-13 16:17:17 +02:00
start = - 1 ;
} else if ( a ! = 0 & & start = = - 1 ) {
start = x ;
}
}
// end of the bitmap line. if start is an actual pixel save the line.
if ( start > = 0 ) {
2017-04-30 02:16:40 +00:00
_lines . push_back ( Line ( start , y , surface . w - start , srcBuf . getRawBuffer ( start ) , textureFormat ) ) ;
2014-07-13 16:17:17 +02:00
}
srcBuf . shiftBy ( surface . w ) ;
}
2014-08-03 20:56:38 +02:00
_version + + ;
2014-07-07 18:17:54 +02:00
}
2014-07-02 19:08:47 +02:00
2014-08-02 21:44:23 +02:00
int getVersion ( ) const {
return _version ;
}
2014-07-07 21:14:58 +02:00
~ BlitImage ( ) {
2014-07-07 18:17:54 +02:00
_surface . free ( ) ;
2014-07-02 19:08:47 +02:00
}
2014-07-13 19:01:23 +02:00
struct Line {
2014-07-13 16:17:17 +02:00
int _x ;
int _y ;
int _length ;
byte * _pixels ;
Graphics : : PixelBuffer _buf ; // This is needed for the conversion.
2014-08-13 20:51:53 +02:00
Line ( ) : _x ( 0 ) , _y ( 0 ) , _length ( 0 ) , _pixels ( nullptr ) { }
2021-12-15 23:55:36 +01:00
Line ( int x , int y , int length , byte * pixels , const Graphics : : PixelFormat & textureFormat ) :
_buf ( gl_get_context ( ) - > fb - > getPixelFormat ( ) , length , DisposeAfterUse : : NO ) ,
_x ( x ) , _y ( y ) , _length ( length ) {
2014-07-13 16:17:17 +02:00
// Performing texture to screen conversion.
Graphics : : PixelBuffer srcBuf ( textureFormat , pixels ) ;
_buf . copyBuffer ( 0 , 0 , length , srcBuf ) ;
_pixels = _buf . getRawBuffer ( ) ;
}
2021-03-15 12:09:14 +02:00
Line & operator = ( const Line & other ) {
if ( this = = & other )
return * this ;
_x = other . _x ;
_y = other . _y ;
if ( _length ! = other . _length | | _buf . getFormat ( ) ! = other . _buf . getFormat ( ) ) {
_buf . free ( ) ;
_buf . create ( other . _buf . getFormat ( ) , other . _length , DisposeAfterUse : : NO ) ;
_length = other . _length ;
}
_buf . copyBuffer ( 0 , 0 , _length , other . _buf ) ;
_pixels = _buf . getRawBuffer ( ) ;
return * this ;
}
2021-03-13 11:28:46 +00:00
Line ( const Line & other ) : _buf ( other . _buf . getFormat ( ) , other . _length , DisposeAfterUse : : NO ) , _x ( other . _x ) , _y ( other . _y ) , _length ( other . _length ) {
2014-07-13 16:17:17 +02:00
_buf . copyBuffer ( 0 , 0 , _length , other . _buf ) ;
_pixels = _buf . getRawBuffer ( ) ;
}
~ Line ( ) {
_buf . free ( ) ;
}
} ;
2014-08-01 19:27:28 +02:00
FORCEINLINE bool clipBlitImage ( TinyGL : : GLContext * c , int & srcX , int & srcY , int & srcWidth , int & srcHeight , int & width , int & height , int & dstX , int & dstY , int & clampWidth , int & clampHeight ) {
2014-07-15 16:32:14 +02:00
if ( srcWidth = = 0 | | srcHeight = = 0 ) {
srcWidth = _surface . w ;
srcHeight = _surface . h ;
}
if ( width = = 0 & & height = = 0 ) {
width = srcWidth ;
height = srcHeight ;
}
2014-08-13 21:03:42 +02:00
if ( dstX > = c - > _scissorRect . right | | dstY > = c - > _scissorRect . bottom )
2014-07-15 16:32:14 +02:00
return false ;
2014-08-13 21:03:42 +02:00
if ( dstX + width < c - > _scissorRect . left | | dstY + height < c - > _scissorRect . top ) {
2014-08-05 13:20:18 +02:00
return false ;
}
2014-08-13 21:03:42 +02:00
if ( dstX < c - > _scissorRect . left ) {
srcX + = ( c - > _scissorRect . left - dstX ) ;
width - = ( c - > _scissorRect . left - dstX ) ;
dstX = c - > _scissorRect . left ;
2014-08-01 19:27:28 +02:00
}
2021-05-04 11:45:03 +03:00
2014-08-13 21:03:42 +02:00
if ( dstY < c - > _scissorRect . top ) {
srcY + = ( c - > _scissorRect . top - dstY ) ;
height - = ( c - > _scissorRect . top - dstY ) ;
dstY = c - > _scissorRect . top ;
2014-08-01 19:27:28 +02:00
}
2014-08-05 13:20:18 +02:00
if ( width < 0 | | height < 0 ) {
return false ;
}
2016-07-22 06:19:41 +02:00
if ( dstX + width > = c - > _scissorRect . right ) {
2014-08-13 21:03:42 +02:00
clampWidth = c - > _scissorRect . right - dstX ;
2014-08-13 14:33:54 +02:00
} else {
2014-07-15 16:32:14 +02:00
clampWidth = width ;
2014-08-13 14:33:54 +02:00
}
2014-07-15 16:32:14 +02:00
2016-07-22 06:19:41 +02:00
if ( dstY + height > = c - > _scissorRect . bottom ) {
2014-08-13 21:03:42 +02:00
clampHeight = c - > _scissorRect . bottom - dstY ;
2014-08-13 14:33:54 +02:00
} else {
2014-07-15 16:32:14 +02:00
clampHeight = height ;
2014-08-13 14:33:54 +02:00
}
2014-07-15 16:32:14 +02:00
return true ;
}
2014-08-10 22:02:06 +02:00
// Blits an image to the z buffer.
// The function only supports clipped blitting without any type of transformation or tinting.
2014-07-25 15:45:12 +02:00
void tglBlitZBuffer ( int dstX , int dstY ) {
TinyGL : : GLContext * c = TinyGL : : gl_get_context ( ) ;
int clampWidth , clampHeight ;
int width = _surface . w , height = _surface . h ;
int srcWidth = 0 , srcHeight = 0 ;
2014-08-01 19:27:28 +02:00
int srcX = 0 , srcY = 0 ;
if ( clipBlitImage ( c , srcX , srcY , srcWidth , srcHeight , width , height , dstX , dstY , clampWidth , clampHeight ) = = false )
2014-07-25 15:45:12 +02:00
return ;
2021-12-07 20:40:32 +01:00
int fbWidth = c - > fb - > getPixelBufferWidth ( ) ;
2014-08-10 22:02:06 +02:00
Graphics : : PixelBuffer srcBuf ( _surface . format , ( byte * ) const_cast < void * > ( _surface . getPixels ( ) ) ) ; // Blit image buffer
2021-12-09 21:10:53 +01:00
Graphics : : PixelBuffer dstBuf ( _surface . format , ( byte * ) const_cast < uint * > ( c - > fb - > getZBuffer ( ) ) ) ; // TinyGL z buffer
2014-07-25 15:45:12 +02:00
2014-08-02 21:46:07 +02:00
srcBuf . shiftBy ( srcY * _surface . w ) ;
2014-08-01 19:27:28 +02:00
2021-12-07 20:40:32 +01:00
dstBuf . shiftBy ( dstY * fbWidth ) ;
2014-08-10 19:35:29 +02:00
for ( int y = 0 ; y < clampHeight ; y + + ) {
2014-08-02 21:46:07 +02:00
dstBuf . copyBuffer ( dstX , srcX , clampWidth , srcBuf ) ;
2021-12-07 20:40:32 +01:00
dstBuf . shiftBy ( fbWidth ) ;
2014-08-01 19:27:28 +02:00
srcBuf . shiftBy ( _surface . w ) ;
2014-07-25 15:45:12 +02:00
}
}
2014-08-10 20:29:09 +02:00
template < bool kDisableColoring , bool kDisableBlending , bool kEnableAlphaBlending >
2014-07-17 13:38:23 +02:00
FORCEINLINE void tglBlitRLE ( int dstX , int dstY , int srcX , int srcY , int srcWidth , int srcHeight , float aTint , float rTint , float gTint , float bTint ) ;
2014-07-15 16:32:14 +02:00
2014-08-10 20:29:09 +02:00
template < bool kDisableBlending , bool kDisableColoring , bool kFlipVertical , bool kFlipHorizontal >
2014-07-17 13:38:23 +02:00
FORCEINLINE void tglBlitSimple ( int dstX , int dstY , int srcX , int srcY , int srcWidth , int srcHeight , float aTint , float rTint , float gTint , float bTint ) ;
2014-07-15 16:32:14 +02:00
2014-08-10 20:29:09 +02:00
template < bool kDisableBlending , bool kDisableColoring , bool kFlipVertical , bool kFlipHorizontal >
2014-07-17 13:38:23 +02:00
FORCEINLINE void tglBlitScale ( int dstX , int dstY , int width , int height , int srcX , int srcY , int srcWidth , int srcHeight , float aTint , float rTint , float gTint , float bTint ) ;
2014-07-15 16:32:14 +02:00
2014-08-10 20:29:09 +02:00
template < bool kDisableBlending , bool kDisableColoring , bool kFlipVertical , bool kFlipHorizontal >
2014-07-17 13:38:23 +02:00
FORCEINLINE void tglBlitRotoScale ( int dstX , int dstY , int width , int height , int srcX , int srcY , int srcWidth , int srcHeight , int rotation ,
2021-12-15 23:55:36 +01:00
int originX , int originY , float aTint , float rTint , float gTint , float bTint ) ;
2014-07-15 16:32:14 +02:00
2014-08-10 20:17:31 +02:00
//Utility function that calls the correct blitting function.
2014-08-10 20:29:09 +02:00
template < bool kDisableBlending , bool kDisableColoring , bool kDisableTransform , bool kFlipVertical , bool kFlipHorizontal , bool kEnableAlphaBlending >
2014-07-15 16:32:14 +02:00
FORCEINLINE void tglBlitGeneric ( const BlitTransform & transform ) {
2014-08-10 20:29:09 +02:00
if ( kDisableTransform ) {
if ( ( kDisableBlending | | kEnableAlphaBlending ) & & kFlipVertical = = false & & kFlipHorizontal = = false ) {
2014-08-13 21:11:24 +02:00
tglBlitRLE < kDisableColoring , kDisableBlending , kEnableAlphaBlending > ( transform . _destinationRectangle . left ,
2021-05-04 11:45:03 +03:00
transform . _destinationRectangle . top , transform . _sourceRectangle . left , transform . _sourceRectangle . top ,
2014-08-13 21:11:24 +02:00
transform . _sourceRectangle . width ( ) , transform . _sourceRectangle . height ( ) , transform . _aTint ,
transform . _rTint , transform . _gTint , transform . _bTint ) ;
2014-07-15 16:32:14 +02:00
} else {
2021-05-04 11:45:03 +03:00
tglBlitSimple < kDisableBlending , kDisableColoring , kFlipVertical , kFlipHorizontal > ( transform . _destinationRectangle . left ,
transform . _destinationRectangle . top , transform . _sourceRectangle . left , transform . _sourceRectangle . top ,
2014-08-13 21:11:24 +02:00
transform . _sourceRectangle . width ( ) , transform . _sourceRectangle . height ( ) ,
2014-07-15 16:32:14 +02:00
transform . _aTint , transform . _rTint , transform . _gTint , transform . _bTint ) ;
}
} else {
if ( transform . _rotation = = 0 ) {
2014-08-13 21:11:24 +02:00
tglBlitScale < kDisableBlending , kDisableColoring , kFlipVertical , kFlipHorizontal > ( transform . _destinationRectangle . left ,
transform . _destinationRectangle . top , transform . _destinationRectangle . width ( ) , transform . _destinationRectangle . height ( ) ,
transform . _sourceRectangle . left , transform . _sourceRectangle . top , transform . _sourceRectangle . width ( ) , transform . _sourceRectangle . height ( ) ,
transform . _aTint , transform . _rTint , transform . _gTint , transform . _bTint ) ;
2014-07-15 16:32:14 +02:00
} else {
2014-08-13 21:11:24 +02:00
tglBlitRotoScale < kDisableBlending , kDisableColoring , kFlipVertical , kFlipHorizontal > ( transform . _destinationRectangle . left ,
transform . _destinationRectangle . top , transform . _destinationRectangle . width ( ) , transform . _destinationRectangle . height ( ) ,
transform . _sourceRectangle . left , transform . _sourceRectangle . top , transform . _sourceRectangle . width ( ) ,
transform . _sourceRectangle . height ( ) , transform . _rotation , transform . _originX , transform . _originY , transform . _aTint ,
transform . _rTint , transform . _gTint , transform . _bTint ) ;
2014-07-15 16:32:14 +02:00
}
}
}
2014-08-13 21:13:50 +02:00
int getWidth ( ) const { return _surface . w ; }
int getHeight ( ) const { return _surface . h ; }
2016-07-28 23:32:43 +00:00
void incRefCount ( ) { _refcount + + ; }
void dispose ( ) { if ( - - _refcount = = 0 ) _isDisposed = true ; }
2014-08-13 21:13:50 +02:00
bool isDisposed ( ) const { return _isDisposed ; }
private :
2014-08-10 19:34:47 +02:00
bool _isDisposed ;
2014-07-17 13:22:15 +02:00
bool _binaryTransparent ;
2014-07-13 16:17:17 +02:00
Common : : Array < Line > _lines ;
2014-07-07 18:17:54 +02:00
Graphics : : Surface _surface ;
2014-08-02 21:44:23 +02:00
int _version ;
2016-07-28 23:32:43 +00:00
int _refcount ;
2014-07-07 18:17:54 +02:00
} ;
2021-12-07 00:31:48 +00:00
} // end of namespace TinyGL
2021-12-06 13:57:41 +01:00
void tglGetBlitImageSize ( TinyGL : : BlitImage * blitImage , int & width , int & height ) {
2014-08-13 21:13:50 +02:00
width = blitImage - > getWidth ( ) ;
height = blitImage - > getHeight ( ) ;
2014-07-27 19:51:16 +02:00
}
2021-12-06 13:57:41 +01:00
void tglIncBlitImageRef ( TinyGL : : BlitImage * blitImage ) {
2016-07-28 23:32:43 +00:00
blitImage - > incRefCount ( ) ;
}
2021-12-06 13:57:41 +01:00
int tglGetBlitImageVersion ( TinyGL : : BlitImage * blitImage ) {
2014-08-02 21:44:23 +02:00
return blitImage - > getVersion ( ) ;
}
2021-12-06 13:57:41 +01:00
TinyGL : : BlitImage * tglGenBlitImage ( ) {
2014-07-12 11:51:11 +02:00
TinyGL : : GLContext * c = TinyGL : : gl_get_context ( ) ;
2021-12-06 13:57:41 +01:00
TinyGL : : BlitImage * image = new TinyGL : : BlitImage ( ) ;
2014-08-09 12:17:40 +02:00
c - > _blitImages . push_back ( image ) ;
2014-07-07 21:14:58 +02:00
return image ;
2014-07-07 18:17:54 +02:00
}
2021-12-06 13:57:41 +01:00
void tglUploadBlitImage ( TinyGL : : BlitImage * blitImage , const Graphics : : Surface & surface , uint32 colorKey , bool applyColorKey ) {
2014-07-07 21:14:58 +02:00
if ( blitImage ! = nullptr ) {
blitImage - > loadData ( surface , colorKey , applyColorKey ) ;
}
2014-07-07 18:17:54 +02:00
}
2021-12-06 13:57:41 +01:00
void tglDeleteBlitImage ( TinyGL : : BlitImage * blitImage ) {
2014-08-13 15:38:00 +02:00
if ( blitImage ! = nullptr ) {
2014-08-13 21:13:50 +02:00
blitImage - > dispose ( ) ;
2014-08-13 15:38:00 +02:00
}
2014-07-07 18:17:54 +02:00
}
2021-12-06 13:57:41 +01:00
namespace TinyGL {
2014-08-10 22:02:06 +02:00
// This function uses RLE encoding to skip transparent bitmap parts
2014-08-13 21:21:09 +02:00
// This blit only supports tinting but it will fall back to simpleBlit
// if flipping is required (or anything more complex than that, including rotationd and scaling).
2014-08-10 20:29:09 +02:00
template < bool kDisableColoring , bool kDisableBlending , bool kEnableAlphaBlending >
2021-12-07 19:58:03 +01:00
FORCEINLINE void BlitImage : : tglBlitRLE ( int dstX , int dstY , int srcX , int srcY , int srcWidth , int srcHeight , float aTint , float rTint , float gTint , float bTint ) {
GLContext * c = gl_get_context ( ) ;
2014-07-02 19:08:47 +02:00
2014-07-13 18:49:27 +02:00
int clampWidth , clampHeight ;
int width = srcWidth , height = srcHeight ;
2014-08-01 19:27:28 +02:00
if ( clipBlitImage ( c , srcX , srcY , srcWidth , srcHeight , width , height , dstX , dstY , clampWidth , clampHeight ) = = false )
2014-07-13 18:49:27 +02:00
return ;
2014-07-17 13:22:15 +02:00
if ( aTint < = 0.0f )
return ;
2021-12-07 20:40:32 +01:00
int fbWidth = c - > fb - > getPixelBufferWidth ( ) ;
2014-07-15 16:32:14 +02:00
Graphics : : PixelBuffer srcBuf ( _surface . format , ( byte * ) _surface . getPixels ( ) ) ;
srcBuf . shiftBy ( srcX + ( srcY * _surface . w ) ) ;
2014-07-07 18:17:54 +02:00
2021-12-07 20:40:32 +01:00
Graphics : : PixelBuffer dstBuf ( c - > fb - > getPixelFormat ( ) , c - > fb - > getPixelBuffer ( ) ) ;
dstBuf . shiftBy ( dstY * fbWidth + dstX ) ;
2014-07-07 18:17:54 +02:00
2021-12-07 20:40:32 +01:00
int kBytesPerPixel = c - > fb - > getPixelFormat ( ) . bytesPerPixel ;
2014-07-13 19:00:14 +02:00
2014-07-16 14:18:01 +02:00
uint32 lineIndex = 0 ;
2014-07-13 19:00:14 +02:00
int maxY = srcY + clampHeight ;
int maxX = srcX + clampWidth ;
2014-07-15 16:32:14 +02:00
while ( lineIndex < _lines . size ( ) & & _lines [ lineIndex ] . _y < srcY ) {
2014-07-13 19:00:14 +02:00
lineIndex + + ;
}
2014-07-17 13:22:15 +02:00
2021-05-04 11:45:03 +03:00
if ( _binaryTransparent | | ( kDisableBlending | | ! kEnableAlphaBlending ) ) { // If bitmap is binary transparent or if we need complex forms of blending (not just alpha) we need to use writePixel, which is slower
2014-07-17 13:22:15 +02:00
while ( lineIndex < _lines . size ( ) & & _lines [ lineIndex ] . _y < maxY ) {
const BlitImage : : Line & l = _lines [ lineIndex ] ;
if ( l . _x < maxX & & l . _x + l . _length > srcX ) {
int length = l . _length ;
int skipStart = ( l . _x < srcX ) ? ( srcX - l . _x ) : 0 ;
length - = skipStart ;
int skipEnd = ( l . _x + l . _length > maxX ) ? ( l . _x + l . _length - maxX ) : 0 ;
length - = skipEnd ;
2014-08-10 20:29:09 +02:00
if ( kDisableColoring & & ( kEnableAlphaBlending = = false | | kDisableBlending ) ) {
2021-12-07 20:40:32 +01:00
memcpy ( dstBuf . getRawBuffer ( ( l . _y - srcY ) * fbWidth + MAX ( l . _x - srcX , 0 ) ) ,
2014-07-17 13:22:15 +02:00
l . _pixels + skipStart * kBytesPerPixel , length * kBytesPerPixel ) ;
} else {
int xStart = MAX ( l . _x - srcX , 0 ) ;
2014-08-10 20:29:09 +02:00
if ( kDisableColoring ) {
2021-12-07 20:40:32 +01:00
dstBuf . copyBuffer ( xStart + ( l . _y - srcY ) * fbWidth , skipStart , length , l . _buf ) ;
2014-07-18 19:56:26 +02:00
} else {
for ( int x = xStart ; x < xStart + length ; x + + ) {
byte aDst , rDst , gDst , bDst ;
srcBuf . getARGBAt ( ( l . _y - srcY ) * _surface . w + x , aDst , rDst , gDst , bDst ) ;
2021-12-07 20:40:32 +01:00
c - > fb - > writePixel ( ( dstX + x ) + ( dstY + ( l . _y - srcY ) ) * fbWidth , aDst * aTint , rDst * rTint , gDst * gTint , bDst * bTint ) ;
2014-07-17 13:22:15 +02:00
}
}
2014-07-07 18:17:54 +02:00
}
}
2014-07-17 13:22:15 +02:00
lineIndex + + ;
}
2014-08-10 22:02:06 +02:00
} else { // Otherwise can use setPixel in some cases which speeds up things quite a bit
2014-07-17 13:22:15 +02:00
while ( lineIndex < _lines . size ( ) & & _lines [ lineIndex ] . _y < maxY ) {
const BlitImage : : Line & l = _lines [ lineIndex ] ;
if ( l . _x < maxX & & l . _x + l . _length > srcX ) {
int length = l . _length ;
int skipStart = ( l . _x < srcX ) ? ( srcX - l . _x ) : 0 ;
length - = skipStart ;
int skipEnd = ( l . _x + l . _length > maxX ) ? ( l . _x + l . _length - maxX ) : 0 ;
length - = skipEnd ;
2014-08-10 20:29:09 +02:00
if ( kDisableColoring & & ( kEnableAlphaBlending = = false | | kDisableBlending ) ) {
2021-12-07 20:40:32 +01:00
memcpy ( dstBuf . getRawBuffer ( ( l . _y - srcY ) * fbWidth + MAX ( l . _x - srcX , 0 ) ) ,
2014-07-17 13:22:15 +02:00
l . _pixels + skipStart * kBytesPerPixel , length * kBytesPerPixel ) ;
} else {
int xStart = MAX ( l . _x - srcX , 0 ) ;
for ( int x = xStart ; x < xStart + length ; x + + ) {
byte aDst , rDst , gDst , bDst ;
srcBuf . getARGBAt ( ( l . _y - srcY ) * _surface . w + x , aDst , rDst , gDst , bDst ) ;
2014-08-10 20:29:09 +02:00
if ( kDisableColoring ) {
2014-07-17 13:22:15 +02:00
if ( aDst ! = 0xFF ) {
2021-12-07 20:40:32 +01:00
c - > fb - > writePixel ( ( dstX + x ) + ( dstY + ( l . _y - srcY ) ) * fbWidth , aDst , rDst , gDst , bDst ) ;
2014-07-17 13:22:15 +02:00
} else {
2021-12-07 20:40:32 +01:00
dstBuf . setPixelAt ( x + ( l . _y - srcY ) * fbWidth , aDst , rDst , gDst , bDst ) ;
2014-07-17 13:22:15 +02:00
}
} else {
2021-12-07 20:40:32 +01:00
c - > fb - > writePixel ( ( dstX + x ) + ( dstY + ( l . _y - srcY ) ) * fbWidth , aDst * aTint , rDst * rTint , gDst * gTint , bDst * bTint ) ;
2014-07-17 13:22:15 +02:00
}
}
}
}
lineIndex + + ;
2014-07-02 19:08:47 +02:00
}
}
2014-07-07 18:17:54 +02:00
}
2014-08-10 22:02:06 +02:00
// This blit function is called when flipping is needed but transformation isn't.
2014-08-10 20:29:09 +02:00
template < bool kDisableBlending , bool kDisableColoring , bool kFlipVertical , bool kFlipHorizontal >
2021-12-07 19:58:03 +01:00
FORCEINLINE void BlitImage : : tglBlitSimple ( int dstX , int dstY , int srcX , int srcY , int srcWidth , int srcHeight , float aTint , float rTint , float gTint , float bTint ) {
GLContext * c = gl_get_context ( ) ;
2014-07-12 11:41:55 +02:00
2014-07-13 18:49:27 +02:00
int clampWidth , clampHeight ;
int width = srcWidth , height = srcHeight ;
2014-08-01 19:27:28 +02:00
if ( clipBlitImage ( c , srcX , srcY , srcWidth , srcHeight , width , height , dstX , dstY , clampWidth , clampHeight ) = = false )
2014-07-13 18:49:27 +02:00
return ;
2014-07-12 11:41:55 +02:00
2014-07-15 16:32:14 +02:00
Graphics : : PixelBuffer srcBuf ( _surface . format , ( byte * ) _surface . getPixels ( ) ) ;
2014-07-12 11:41:55 +02:00
2014-08-10 20:29:09 +02:00
if ( kFlipVertical ) {
2014-08-05 13:19:57 +02:00
srcBuf . shiftBy ( ( ( srcHeight - srcY - 1 ) * _surface . w ) ) ;
2014-07-13 18:49:27 +02:00
} else {
2014-08-05 13:19:57 +02:00
srcBuf . shiftBy ( ( srcY * _surface . w ) ) ;
2014-07-13 18:49:27 +02:00
}
2014-07-12 11:41:55 +02:00
2021-12-07 20:40:32 +01:00
Graphics : : PixelBuffer dstBuf ( c - > fb - > getPixelFormat ( ) , c - > fb - > getPixelBuffer ( ) ) ;
int fbWidth = c - > fb - > getPixelBufferWidth ( ) ;
2014-07-12 11:41:55 +02:00
2014-08-10 19:35:29 +02:00
for ( int y = 0 ; y < clampHeight ; y + + ) {
for ( int x = 0 ; x < clampWidth ; + + x ) {
2014-07-13 18:49:27 +02:00
byte aDst , rDst , gDst , bDst ;
2014-08-10 20:29:09 +02:00
if ( kFlipHorizontal ) {
2014-08-10 19:35:29 +02:00
srcBuf . getARGBAt ( srcX + clampWidth - x , aDst , rDst , gDst , bDst ) ;
2014-07-13 18:49:27 +02:00
} else {
2014-08-10 19:35:29 +02:00
srcBuf . getARGBAt ( srcX + x , aDst , rDst , gDst , bDst ) ;
2014-07-13 18:49:27 +02:00
}
2014-08-10 22:02:06 +02:00
// Those branches are needed to favor speed: avoiding writePixel always yield a huge performance boost when blitting images.
2021-05-04 11:45:03 +03:00
if ( kDisableColoring ) {
2014-08-10 20:29:09 +02:00
if ( kDisableBlending & & aDst ! = 0 ) {
2021-12-07 20:40:32 +01:00
dstBuf . setPixelAt ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst , rDst , gDst , bDst ) ;
2014-07-13 18:49:27 +02:00
} else {
2021-12-07 20:40:32 +01:00
c - > fb - > writePixel ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst , rDst , gDst , bDst ) ;
2014-07-13 18:49:27 +02:00
}
} else {
2014-08-10 20:29:09 +02:00
if ( kDisableBlending & & aDst * aTint ! = 0 ) {
2021-12-07 20:40:32 +01:00
dstBuf . setPixelAt ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst * aTint , rDst * rTint , gDst * gTint , bDst * bTint ) ;
2014-07-13 18:49:27 +02:00
} else {
2021-12-07 20:40:32 +01:00
c - > fb - > writePixel ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst * aTint , rDst * rTint , gDst * gTint , bDst * bTint ) ;
2014-07-13 18:49:27 +02:00
}
}
}
2014-08-10 20:29:09 +02:00
if ( kFlipVertical ) {
2014-07-15 16:32:14 +02:00
srcBuf . shiftBy ( - _surface . w ) ;
2014-07-13 18:49:27 +02:00
} else {
2014-07-15 16:32:14 +02:00
srcBuf . shiftBy ( _surface . w ) ;
2014-07-13 18:49:27 +02:00
}
}
}
2014-07-12 11:41:55 +02:00
2014-08-13 21:21:09 +02:00
// This function is called when scale is needed: it uses a simple nearest
// filter to scale the blit image before copying it to the screen.
2014-08-10 20:29:09 +02:00
template < bool kDisableBlending , bool kDisableColoring , bool kFlipVertical , bool kFlipHorizontal >
2021-12-07 19:58:03 +01:00
FORCEINLINE void BlitImage : : tglBlitScale ( int dstX , int dstY , int width , int height , int srcX , int srcY , int srcWidth , int srcHeight ,
2021-12-15 23:55:36 +01:00
float aTint , float rTint , float gTint , float bTint ) {
2021-12-07 19:58:03 +01:00
GLContext * c = gl_get_context ( ) ;
2014-07-12 11:41:55 +02:00
2014-07-13 18:49:27 +02:00
int clampWidth , clampHeight ;
2014-08-01 19:27:28 +02:00
if ( clipBlitImage ( c , srcX , srcY , srcWidth , srcHeight , width , height , dstX , dstY , clampWidth , clampHeight ) = = false )
2014-07-13 18:49:27 +02:00
return ;
2014-07-12 11:41:55 +02:00
2014-07-15 16:32:14 +02:00
Graphics : : PixelBuffer srcBuf ( _surface . format , ( byte * ) _surface . getPixels ( ) ) ;
srcBuf . shiftBy ( srcX + ( srcY * _surface . w ) ) ;
2014-07-12 11:41:55 +02:00
2021-12-07 20:40:32 +01:00
Graphics : : PixelBuffer dstBuf ( c - > fb - > getPixelFormat ( ) , c - > fb - > getPixelBuffer ( ) ) ;
int fbWidth = c - > fb - > getPixelBufferWidth ( ) ;
2014-07-12 11:41:55 +02:00
2014-08-10 19:35:29 +02:00
for ( int y = 0 ; y < clampHeight ; y + + ) {
for ( int x = 0 ; x < clampWidth ; + + x ) {
2014-07-13 18:49:27 +02:00
byte aDst , rDst , gDst , bDst ;
int xSource , ySource ;
2014-08-10 20:29:09 +02:00
if ( kFlipVertical ) {
2014-08-10 19:35:29 +02:00
ySource = clampHeight - y - 1 ;
2014-07-13 18:49:27 +02:00
} else {
2014-08-10 19:35:29 +02:00
ySource = y ;
2014-07-13 18:49:27 +02:00
}
2014-08-10 20:29:09 +02:00
if ( kFlipHorizontal ) {
2014-08-10 19:35:29 +02:00
xSource = clampWidth - x - 1 ;
2014-07-13 18:49:27 +02:00
} else {
2014-08-10 19:35:29 +02:00
xSource = x ;
2014-07-13 18:49:27 +02:00
}
2014-07-15 16:32:14 +02:00
srcBuf . getARGBAt ( ( ( ySource * srcHeight ) / height ) * _surface . w + ( ( xSource * srcWidth ) / width ) , aDst , rDst , gDst , bDst ) ;
2014-07-13 18:49:27 +02:00
2014-08-10 20:29:09 +02:00
if ( kDisableColoring ) {
if ( kDisableBlending & & aDst ! = 0 ) {
2021-12-07 20:40:32 +01:00
dstBuf . setPixelAt ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst , rDst , gDst , bDst ) ;
2014-07-12 11:41:55 +02:00
} else {
2021-12-07 20:40:32 +01:00
c - > fb - > writePixel ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst , rDst , gDst , bDst ) ;
2014-07-12 11:41:55 +02:00
}
2014-07-13 18:49:27 +02:00
} else {
2014-08-10 20:29:09 +02:00
if ( kDisableBlending & & aDst * aTint ! = 0 ) {
2021-12-07 20:40:32 +01:00
dstBuf . setPixelAt ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst * aTint , rDst * rTint , gDst * gTint , bDst * bTint ) ;
2014-07-12 11:41:55 +02:00
} else {
2021-12-07 20:40:32 +01:00
c - > fb - > writePixel ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst * aTint , rDst * rTint , gDst * gTint , bDst * bTint ) ;
2014-07-12 11:41:55 +02:00
}
2014-07-13 18:49:27 +02:00
}
}
}
}
2014-08-10 22:02:06 +02:00
/*
The below two functions are adapted from SDL_rotozoom . c ,
taken from SDL_gfx - 2.0 .18 .
Its copyright notice :
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
SDL_rotozoom . c : rotozoomer , zoomer and shrinker for 32 bit or 8 bit surfaces
Copyright ( C ) 2001 - 2012 Andreas Schiffler
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source
distribution .
Andreas Schiffler - - aschiffler at ferzkopp dot net
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
The functions have been adapted for different structures and coordinate
systems .
*/
2014-08-10 20:29:09 +02:00
template < bool kDisableBlending , bool kDisableColoring , bool kFlipVertical , bool kFlipHorizontal >
2021-12-07 19:58:03 +01:00
FORCEINLINE void BlitImage : : tglBlitRotoScale ( int dstX , int dstY , int width , int height , int srcX , int srcY , int srcWidth , int srcHeight , int rotation ,
2021-12-15 23:55:36 +01:00
int originX , int originY , float aTint , float rTint , float gTint , float bTint ) {
2021-12-07 19:58:03 +01:00
GLContext * c = gl_get_context ( ) ;
2021-05-04 11:45:03 +03:00
2014-07-13 18:49:27 +02:00
int clampWidth , clampHeight ;
2014-08-01 19:27:28 +02:00
if ( clipBlitImage ( c , srcX , srcY , srcWidth , srcHeight , width , height , dstX , dstY , clampWidth , clampHeight ) = = false )
2014-07-13 18:49:27 +02:00
return ;
2021-05-04 11:45:03 +03:00
2014-07-15 16:32:14 +02:00
Graphics : : PixelBuffer srcBuf ( _surface . format , ( byte * ) _surface . getPixels ( ) ) ;
srcBuf . shiftBy ( srcX + ( srcY * _surface . w ) ) ;
2021-12-07 20:40:32 +01:00
int fbWidth = c - > fb - > getPixelBufferWidth ( ) ;
2021-05-04 11:45:03 +03:00
2021-12-07 20:40:32 +01:00
Graphics : : PixelBuffer dstBuf ( c - > fb - > getPixelFormat ( ) , c - > fb - > getPixelBuffer ( ) ) ;
2021-05-04 11:45:03 +03:00
2014-07-13 18:49:27 +02:00
// Transform destination rectangle accordingly.
Common : : Rect destinationRectangle = rotateRectangle ( dstX , dstY , width , height , rotation , originX , originY ) ;
2021-05-04 11:45:03 +03:00
2021-12-07 20:40:32 +01:00
if ( dstX + destinationRectangle . width ( ) > fbWidth )
clampWidth = fbWidth - dstX ;
2014-07-13 18:49:27 +02:00
else
clampWidth = destinationRectangle . width ( ) ;
2021-12-07 20:40:32 +01:00
if ( dstY + destinationRectangle . height ( ) > c - > fb - > getPixelBufferHeight ( ) )
clampHeight = c - > fb - > getPixelBufferHeight ( ) - dstY ;
2014-07-13 18:49:27 +02:00
else
clampHeight = destinationRectangle . height ( ) ;
2021-05-04 11:45:03 +03:00
2014-07-13 18:49:27 +02:00
uint32 invAngle = 360 - ( rotation % 360 ) ;
2020-09-23 23:20:23 +02:00
float invCos = cos ( invAngle * ( float ) M_PI / 180.0f ) ;
float invSin = sin ( invAngle * ( float ) M_PI / 180.0f ) ;
2021-05-04 11:45:03 +03:00
2014-07-13 18:49:27 +02:00
int icosx = ( int ) ( invCos * ( 65536.0f * srcWidth / width ) ) ;
int isinx = ( int ) ( invSin * ( 65536.0f * srcWidth / width ) ) ;
int icosy = ( int ) ( invCos * ( 65536.0f * srcHeight / height ) ) ;
int isiny = ( int ) ( invSin * ( 65536.0f * srcHeight / height ) ) ;
2021-05-04 11:45:03 +03:00
2014-07-13 18:49:27 +02:00
int xd = ( srcX + originX ) < < 16 ;
int yd = ( srcY + originY ) < < 16 ;
2014-07-16 01:56:12 +02:00
int cx = originX * ( ( float ) width / srcWidth ) ;
int cy = originY * ( ( float ) height / srcHeight ) ;
2021-05-04 11:45:03 +03:00
2014-07-13 18:49:27 +02:00
int ax = - icosx * cx ;
int ay = - isiny * cx ;
int sw = width - 1 ;
int sh = height - 1 ;
2021-05-04 11:45:03 +03:00
2014-08-10 19:35:29 +02:00
for ( int y = 0 ; y < clampHeight ; y + + ) {
int t = cy - y ;
2014-07-13 18:49:27 +02:00
int sdx = ax + ( isinx * t ) + xd ;
int sdy = ay - ( icosy * t ) + yd ;
2014-08-10 19:35:29 +02:00
for ( int x = 0 ; x < clampWidth ; + + x ) {
2014-07-13 18:49:27 +02:00
byte aDst , rDst , gDst , bDst ;
2021-05-04 11:45:03 +03:00
2014-07-13 18:49:27 +02:00
int dx = ( sdx > > 16 ) ;
int dy = ( sdy > > 16 ) ;
2021-05-04 11:45:03 +03:00
2014-08-13 21:21:09 +02:00
if ( kFlipHorizontal ) {
2014-07-13 18:49:27 +02:00
dx = sw - dx ;
2014-08-13 21:21:09 +02:00
}
if ( kFlipVertical ) {
2014-07-13 18:49:27 +02:00
dy = sh - dy ;
2014-08-13 21:21:09 +02:00
}
2021-05-04 11:45:03 +03:00
2014-07-13 18:49:27 +02:00
if ( ( dx > = 0 ) & & ( dy > = 0 ) & & ( dx < srcWidth ) & & ( dy < srcHeight ) ) {
2014-07-15 16:32:14 +02:00
srcBuf . getARGBAt ( dy * _surface . w + dx , aDst , rDst , gDst , bDst ) ;
2014-08-10 20:29:09 +02:00
if ( kDisableColoring ) {
if ( kDisableBlending & & aDst ! = 0 ) {
2021-12-07 20:40:32 +01:00
dstBuf . setPixelAt ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst , rDst , gDst , bDst ) ;
2014-07-12 11:41:55 +02:00
} else {
2021-12-07 20:40:32 +01:00
c - > fb - > writePixel ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst , rDst , gDst , bDst ) ;
2014-07-12 11:41:55 +02:00
}
} else {
2014-08-10 20:29:09 +02:00
if ( kDisableBlending & & aDst * aTint ! = 0 ) {
2021-12-07 20:40:32 +01:00
dstBuf . setPixelAt ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst * aTint , rDst * rTint , gDst * gTint , bDst * bTint ) ;
2014-07-12 11:41:55 +02:00
} else {
2021-12-07 20:40:32 +01:00
c - > fb - > writePixel ( ( dstX + x ) + ( dstY + y ) * fbWidth , aDst * aTint , rDst * rTint , gDst * gTint , bDst * bTint ) ;
2014-07-12 11:41:55 +02:00
}
}
}
2014-07-13 18:49:27 +02:00
sdx + = icosx ;
sdy + = isiny ;
2014-07-12 11:41:55 +02:00
}
}
2014-07-16 02:24:34 +02:00
}
2021-12-06 13:57:41 +01:00
} // end of namespace TinyGL
void tglBlit ( TinyGL : : BlitImage * blitImage , int x , int y ) {
TinyGL : : GLContext * c = TinyGL : : gl_get_context ( ) ;
TinyGL : : BlitTransform transform ( x , y ) ;
c - > issueDrawCall ( new TinyGL : : BlittingDrawCall ( blitImage , transform , TinyGL : : BlittingDrawCall : : BlitMode_Regular ) ) ;
2014-07-23 15:18:57 +02:00
}
2021-12-06 13:57:41 +01:00
void tglBlit ( TinyGL : : BlitImage * blitImage , const TinyGL : : BlitTransform & transform ) {
TinyGL : : GLContext * c = TinyGL : : gl_get_context ( ) ;
c - > issueDrawCall ( new TinyGL : : BlittingDrawCall ( blitImage , transform , TinyGL : : BlittingDrawCall : : BlitMode_Regular ) ) ;
2014-07-23 15:18:57 +02:00
}
2021-12-06 13:57:41 +01:00
void tglBlitNoBlend ( TinyGL : : BlitImage * blitImage , const TinyGL : : BlitTransform & transform ) {
TinyGL : : GLContext * c = TinyGL : : gl_get_context ( ) ;
c - > issueDrawCall ( new TinyGL : : BlittingDrawCall ( blitImage , transform , TinyGL : : BlittingDrawCall : : BlitMode_NoBlend ) ) ;
2014-07-23 15:18:57 +02:00
}
2021-12-06 13:57:41 +01:00
void tglBlitFast ( TinyGL : : BlitImage * blitImage , int x , int y ) {
TinyGL : : GLContext * c = TinyGL : : gl_get_context ( ) ;
TinyGL : : BlitTransform transform ( x , y ) ;
c - > issueDrawCall ( new TinyGL : : BlittingDrawCall ( blitImage , transform , TinyGL : : BlittingDrawCall : : BlitMode_Fast ) ) ;
2014-07-23 15:18:57 +02:00
}
2021-12-06 13:57:41 +01:00
void tglBlitZBuffer ( TinyGL : : BlitImage * blitImage , int x , int y ) {
TinyGL : : GLContext * c = TinyGL : : gl_get_context ( ) ;
TinyGL : : BlitTransform transform ( x , y ) ;
c - > issueDrawCall ( new TinyGL : : BlittingDrawCall ( blitImage , transform , TinyGL : : BlittingDrawCall : : BlitMode_ZBuffer ) ) ;
2014-07-25 15:45:12 +02:00
}
2021-12-06 13:57:41 +01:00
namespace TinyGL {
2014-07-23 15:18:57 +02:00
namespace Internal {
2014-08-10 20:18:04 +02:00
template < bool kEnableAlphaBlending , bool kDisableColor , bool kDisableTransform , bool kDisableBlend >
void tglBlit ( BlitImage * blitImage , const BlitTransform & transform ) {
if ( transform . _flipHorizontally ) {
if ( transform . _flipVertically ) {
blitImage - > tglBlitGeneric < kDisableBlend , kDisableColor , kDisableTransform , true , true , kEnableAlphaBlending > ( transform ) ;
} else {
blitImage - > tglBlitGeneric < kDisableBlend , kDisableColor , kDisableTransform , false , true , kEnableAlphaBlending > ( transform ) ;
}
} else if ( transform . _flipVertically ) {
blitImage - > tglBlitGeneric < kDisableBlend , kDisableColor , kDisableTransform , true , false , kEnableAlphaBlending > ( transform ) ;
} else {
blitImage - > tglBlitGeneric < kDisableBlend , kDisableColor , kDisableTransform , false , false , kEnableAlphaBlending > ( transform ) ;
}
}
template < bool kEnableAlphaBlending , bool kDisableColor , bool kDisableTransform >
void tglBlit ( BlitImage * blitImage , const BlitTransform & transform , bool disableBlend ) {
if ( disableBlend ) {
tglBlit < kEnableAlphaBlending , kDisableColor , kDisableTransform , true > ( blitImage , transform ) ;
} else {
tglBlit < kEnableAlphaBlending , kDisableColor , kDisableTransform , false > ( blitImage , transform ) ;
}
}
template < bool kEnableAlphaBlending , bool kDisableColor >
void tglBlit ( BlitImage * blitImage , const BlitTransform & transform , bool disableTransform , bool disableBlend ) {
if ( disableTransform ) {
tglBlit < kEnableAlphaBlending , kDisableColor , true > ( blitImage , transform , disableBlend ) ;
} else {
tglBlit < kEnableAlphaBlending , kDisableColor , false > ( blitImage , transform , disableBlend ) ;
}
}
template < bool kEnableAlphaBlending >
void tglBlit ( BlitImage * blitImage , const BlitTransform & transform , bool disableColor , bool disableTransform , bool disableBlend ) {
if ( disableColor ) {
tglBlit < kEnableAlphaBlending , true > ( blitImage , transform , disableTransform , disableBlend ) ;
} else {
tglBlit < kEnableAlphaBlending , false > ( blitImage , transform , disableTransform , disableBlend ) ;
}
}
2014-07-07 21:14:58 +02:00
void tglBlit ( BlitImage * blitImage , const BlitTransform & transform ) {
2021-12-06 13:57:41 +01:00
GLContext * c = gl_get_context ( ) ;
2014-07-07 18:17:54 +02:00
bool disableColor = transform . _aTint = = 1.0f & & transform . _bTint = = 1.0f & & transform . _gTint = = 1.0f & & transform . _rTint = = 1.0f ;
2014-07-07 21:14:58 +02:00
bool disableTransform = transform . _destinationRectangle . width ( ) = = 0 & & transform . _destinationRectangle . height ( ) = = 0 & & transform . _rotation = = 0 ;
2021-12-07 19:58:03 +01:00
bool disableBlend = c - > blending_enabled = = false ;
bool enableAlphaBlending = c - > source_blending_factor = = TGL_SRC_ALPHA & & c - > destination_blending_factor = = TGL_ONE_MINUS_SRC_ALPHA ;
2014-08-10 20:18:04 +02:00
2014-07-17 13:22:15 +02:00
if ( enableAlphaBlending ) {
2014-08-10 20:18:04 +02:00
tglBlit < true > ( blitImage , transform , disableColor , disableTransform , disableBlend ) ;
2014-07-07 18:17:54 +02:00
} else {
2014-08-10 20:18:04 +02:00
tglBlit < false > ( blitImage , transform , disableColor , disableTransform , disableBlend ) ;
2014-07-02 19:08:47 +02:00
}
2014-07-07 18:17:54 +02:00
}
2014-07-02 19:08:47 +02:00
2014-07-07 21:14:58 +02:00
void tglBlitNoBlend ( BlitImage * blitImage , const BlitTransform & transform ) {
2014-07-07 18:17:54 +02:00
if ( transform . _flipHorizontally = = false & & transform . _flipVertically = = false ) {
2014-07-17 13:22:15 +02:00
blitImage - > tglBlitGeneric < true , false , false , false , false , false > ( transform ) ;
2014-07-07 18:17:54 +02:00
} else if ( transform . _flipHorizontally = = false ) {
2014-07-17 13:22:15 +02:00
blitImage - > tglBlitGeneric < true , false , false , true , false , false > ( transform ) ;
2014-07-07 18:17:54 +02:00
} else {
2014-07-17 13:22:15 +02:00
blitImage - > tglBlitGeneric < true , false , false , false , true , false > ( transform ) ;
2014-07-02 19:08:47 +02:00
}
2014-07-07 18:17:54 +02:00
}
2014-07-02 19:08:47 +02:00
2014-07-07 21:14:58 +02:00
void tglBlitFast ( BlitImage * blitImage , int x , int y ) {
2014-07-07 18:17:54 +02:00
BlitTransform transform ( x , y ) ;
2014-07-17 13:22:15 +02:00
blitImage - > tglBlitGeneric < true , true , true , false , false , false > ( transform ) ;
2014-07-07 18:17:54 +02:00
}
2014-07-12 11:41:55 +02:00
2014-07-25 15:45:12 +02:00
void tglBlitZBuffer ( BlitImage * blitImage , int x , int y ) {
blitImage - > tglBlitZBuffer ( x , y ) ;
}
2014-07-23 21:37:45 +02:00
void tglCleanupImages ( ) {
2021-12-06 13:57:41 +01:00
GLContext * c = gl_get_context ( ) ;
2014-08-09 12:17:40 +02:00
Common : : List < BlitImage * > : : iterator it = c - > _blitImages . begin ( ) ;
while ( it ! = c - > _blitImages . end ( ) ) {
2014-08-13 21:13:50 +02:00
if ( ( * it ) - > isDisposed ( ) ) {
2014-08-09 12:17:11 +02:00
delete ( * it ) ;
2014-08-09 12:17:40 +02:00
it = c - > _blitImages . erase ( it ) ;
2014-08-09 12:17:11 +02:00
} else {
+ + it ;
2014-07-23 21:37:45 +02:00
}
}
}
2017-04-22 06:28:24 +00:00
void tglBlitSetScissorRect ( const Common : : Rect & rect ) {
2021-12-06 13:57:41 +01:00
gl_get_context ( ) - > _scissorRect = rect ;
2017-04-22 06:28:24 +00:00
}
2021-12-07 19:58:03 +01:00
void tglBlitResetScissorRect ( ) {
2021-12-06 13:57:41 +01:00
GLContext * c = gl_get_context ( ) ;
2016-07-23 17:40:41 +02:00
c - > _scissorRect = c - > renderRect ;
2014-08-01 19:27:28 +02:00
}
2014-07-23 15:18:57 +02:00
} // end of namespace Internal
2014-07-13 18:49:27 +02:00
Common : : Point transformPoint ( float x , float y , int rotation ) {
2020-09-23 23:20:23 +02:00
float rotateRad = rotation * ( float ) M_PI / 180.0f ;
2014-07-13 18:49:27 +02:00
Common : : Point newPoint ;
newPoint . x = x * cos ( rotateRad ) - y * sin ( rotateRad ) ;
newPoint . y = x * sin ( rotateRad ) + y * cos ( rotateRad ) ;
return newPoint ;
}
Common : : Rect rotateRectangle ( int x , int y , int width , int height , int rotation , int originX , int originY ) {
Common : : Point nw , ne , sw , se ;
nw = transformPoint ( x - originX , y - originY , rotation ) ;
ne = transformPoint ( x + width - originX , y - originY , rotation ) ;
2021-10-20 22:20:28 +02:00
sw = transformPoint ( x + width - originX , y + height - originY , rotation ) ;
2014-07-13 18:49:27 +02:00
se = transformPoint ( x - originX , y + height - originY , rotation ) ;
float top = MIN ( nw . y , MIN ( ne . y , MIN ( sw . y , se . y ) ) ) ;
float bottom = MAX ( nw . y , MAX ( ne . y , MAX ( sw . y , se . y ) ) ) ;
float left = MIN ( nw . x , MIN ( ne . x , MIN ( sw . x , se . x ) ) ) ;
float right = MAX ( nw . x , MAX ( ne . x , MAX ( sw . x , se . x ) ) ) ;
Common : : Rect res ;
res . top = ( int32 ) ( floor ( top ) ) + originY ;
res . bottom = ( int32 ) ( ceil ( bottom ) ) + originY ;
res . left = ( int32 ) ( floor ( left ) ) + originX ;
res . right = ( int32 ) ( ceil ( right ) ) + originX ;
return res ;
}
2021-12-06 13:57:41 +01:00
} // end of namespace TinyGL