Updates for pre-multiplied alpha (thanks Hugh)
This commit is contained in:
@@ -14,7 +14,14 @@ namespace lime {
|
|||||||
|
|
||||||
|
|
||||||
void HintColourOrder (bool inRedFirst);
|
void HintColourOrder (bool inRedFirst);
|
||||||
enum { SURF_FLAGS_NOT_REPEAT_IF_NON_PO2 = 0x0001 };
|
|
||||||
|
enum {
|
||||||
|
|
||||||
|
SURF_FLAGS_NOT_REPEAT_IF_NON_PO2 = 0x0001,
|
||||||
|
SURF_FLAGS_USE_PREMULTIPLIED_ALPHA = 0x0002,
|
||||||
|
SURF_FLAGS_HAS_PREMULTIPLIED_ALPHA = 0x0004
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Surface : public Object {
|
class Surface : public Object {
|
||||||
|
|||||||
@@ -3036,6 +3036,30 @@ value lime_bitmap_data_height(value inHandle)
|
|||||||
}
|
}
|
||||||
DEFINE_PRIM(lime_bitmap_data_height,1);
|
DEFINE_PRIM(lime_bitmap_data_height,1);
|
||||||
|
|
||||||
|
value lime_bitmap_data_get_prem_alpha(value inHandle)
|
||||||
|
{
|
||||||
|
Surface *surface;
|
||||||
|
if (AbstractToObject(inHandle,surface))
|
||||||
|
return alloc_bool(surface->GetFlags() & SURF_FLAGS_USE_PREMULTIPLIED_ALPHA);
|
||||||
|
return alloc_null();
|
||||||
|
}
|
||||||
|
DEFINE_PRIM(lime_bitmap_data_get_prem_alpha,1);
|
||||||
|
|
||||||
|
value lime_bitmap_data_set_prem_alpha(value inHandle,value inVal)
|
||||||
|
{
|
||||||
|
Surface *surface;
|
||||||
|
if (AbstractToObject(inHandle,surface))
|
||||||
|
{
|
||||||
|
bool use = val_bool(inVal) && (surface->Format()<pfAlpha);
|
||||||
|
if (use)
|
||||||
|
surface->SetFlags( surface->GetFlags() | SURF_FLAGS_USE_PREMULTIPLIED_ALPHA );
|
||||||
|
else
|
||||||
|
surface->SetFlags( surface->GetFlags() & ~SURF_FLAGS_USE_PREMULTIPLIED_ALPHA );
|
||||||
|
}
|
||||||
|
return alloc_null();
|
||||||
|
}
|
||||||
|
DEFINE_PRIM(lime_bitmap_data_set_prem_alpha,2);
|
||||||
|
|
||||||
value lime_bitmap_data_clear(value inHandle,value inRGB)
|
value lime_bitmap_data_clear(value inHandle,value inRGB)
|
||||||
{
|
{
|
||||||
Surface *surface;
|
Surface *surface;
|
||||||
|
|||||||
@@ -652,6 +652,9 @@ namespace lime {
|
|||||||
|
|
||||||
if (!mBase)
|
if (!mBase)
|
||||||
return;
|
return;
|
||||||
|
if (mFlags & SURF_FLAGS_HAS_PREMULTIPLIED_ALPHA)
|
||||||
|
return;
|
||||||
|
|
||||||
Rect r = Rect (0, 0, mWidth, mHeight);
|
Rect r = Rect (0, 0, mWidth, mHeight);
|
||||||
mVersion++;
|
mVersion++;
|
||||||
if (mTexture)
|
if (mTexture)
|
||||||
@@ -683,6 +686,8 @@ namespace lime {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mFlags |= SURF_FLAGS_HAS_PREMULTIPLIED_ALPHA;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1037,6 +1042,8 @@ namespace lime {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mFlags &= ~SURF_FLAGS_HAS_PREMULTIPLIED_ALPHA;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -390,35 +390,19 @@ namespace lime {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (element.mBlendMode) {
|
|
||||||
|
|
||||||
case bmAdd:
|
|
||||||
|
|
||||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case bmMultiply:
|
|
||||||
|
|
||||||
glBlendFunc (GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case bmScreen:
|
|
||||||
|
|
||||||
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_COLOR);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int progId = 0;
|
int progId = 0;
|
||||||
|
bool premAlpha = false;
|
||||||
|
|
||||||
if ((element.mFlags & DRAW_HAS_TEX) && element.mSurface) {
|
if ((element.mFlags & DRAW_HAS_TEX) && element.mSurface) {
|
||||||
|
|
||||||
|
if (element.mSurface->GetFlags () & SURF_FLAGS_USE_PREMULTIPLIED_ALPHA) {
|
||||||
|
|
||||||
|
premAlpha = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
progId |= PROG_TEXTURE;
|
progId |= PROG_TEXTURE;
|
||||||
|
|
||||||
if (element.mSurface->BytesPP () == 1) {
|
if (element.mSurface->BytesPP () == 1) {
|
||||||
|
|
||||||
progId |= PROG_ALPHA_TEXTURE;
|
progId |= PROG_ALPHA_TEXTURE;
|
||||||
@@ -473,6 +457,31 @@ namespace lime {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch (element.mBlendMode) {
|
||||||
|
|
||||||
|
case bmAdd:
|
||||||
|
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case bmMultiply:
|
||||||
|
|
||||||
|
glBlendFunc (GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case bmScreen:
|
||||||
|
|
||||||
|
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_COLOR);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
glBlendFunc (premAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (prog != lastProg) {
|
if (prog != lastProg) {
|
||||||
|
|
||||||
if (lastProg) {
|
if (lastProg) {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
namespace lime {
|
namespace lime {
|
||||||
|
|
||||||
|
|
||||||
|
static int *sAlpha16Table = 0;
|
||||||
|
|
||||||
bool gFullNPO2Support = false;
|
bool gFullNPO2Support = false;
|
||||||
bool gPartialNPO2Support = false;
|
bool gPartialNPO2Support = false;
|
||||||
|
|
||||||
@@ -68,6 +70,25 @@ namespace lime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int *getAlpha16Table () {
|
||||||
|
|
||||||
|
if (sAlpha16Table == 0) {
|
||||||
|
|
||||||
|
sAlpha16Table = new int[256];
|
||||||
|
|
||||||
|
for (int a = 0; a < 256; a++) {
|
||||||
|
|
||||||
|
sAlpha16Table[a] = a * (1 << 16) / 255;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return sAlpha16Table;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
OpenGLTexture::OpenGLTexture (Surface *inSurface, unsigned int inFlags) {
|
OpenGLTexture::OpenGLTexture (Surface *inSurface, unsigned int inFlags) {
|
||||||
|
|
||||||
mPixelWidth = inSurface->Width ();
|
mPixelWidth = inSurface->Width ();
|
||||||
@@ -75,7 +96,7 @@ namespace lime {
|
|||||||
mDirtyRect = Rect (0, 0);
|
mDirtyRect = Rect (0, 0);
|
||||||
mContextVersion = gTextureContextVersion;
|
mContextVersion = gTextureContextVersion;
|
||||||
|
|
||||||
bool non_po2 = NonPO2Supported (true && (inFlags & SURF_FLAGS_NOT_REPEAT_IF_NON_PO2));
|
bool non_po2 = NonPO2Supported (inFlags & SURF_FLAGS_NOT_REPEAT_IF_NON_PO2);
|
||||||
//printf("Using non-power-of-2 texture %d\n",non_po2);
|
//printf("Using non-power-of-2 texture %d\n",non_po2);
|
||||||
|
|
||||||
int w = non_po2 ? mPixelWidth : UpToPower2 (mPixelWidth);
|
int w = non_po2 ? mPixelWidth : UpToPower2 (mPixelWidth);
|
||||||
@@ -86,7 +107,11 @@ namespace lime {
|
|||||||
|
|
||||||
mTextureWidth = w;
|
mTextureWidth = w;
|
||||||
mTextureHeight = h;
|
mTextureHeight = h;
|
||||||
bool copy_required = inSurface->GetBase () && (w != mPixelWidth || h != mPixelHeight);
|
bool usePreAlpha = inFlags & SURF_FLAGS_USE_PREMULTIPLIED_ALPHA;
|
||||||
|
bool hasPreAlpha = inFlags & SURF_FLAGS_HAS_PREMULTIPLIED_ALPHA;
|
||||||
|
int *multiplyAlpha = usePreAlpha && !hasPreAlpha ? getAlpha16Table () : 0;
|
||||||
|
|
||||||
|
bool copy_required = inSurface->GetBase () && (w != mPixelWidth || h != mPixelHeight || multiplyAlpha);
|
||||||
|
|
||||||
Surface *load = inSurface;
|
Surface *load = inSurface;
|
||||||
|
|
||||||
@@ -96,10 +121,6 @@ namespace lime {
|
|||||||
int pixels = GL_UNSIGNED_BYTE;
|
int pixels = GL_UNSIGNED_BYTE;
|
||||||
int gpuFormat = inSurface->GPUFormat ();
|
int gpuFormat = inSurface->GPUFormat ();
|
||||||
|
|
||||||
//if (inSurface) {
|
|
||||||
//inSurface->multiplyAlpha();
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (!inSurface->GetBase ()) {
|
if (!inSurface->GetBase ()) {
|
||||||
|
|
||||||
if (gpuFormat != fmt)
|
if (gpuFormat != fmt)
|
||||||
@@ -125,20 +146,44 @@ namespace lime {
|
|||||||
for (int y = 0; y < mPixelHeight; y++)
|
for (int y = 0; y < mPixelHeight; y++)
|
||||||
RGBX_to_RGB565 (buffer + y * mTextureWidth * 2, inSurface->Row (y), mPixelWidth);
|
RGBX_to_RGB565 (buffer + y * mTextureWidth * 2, inSurface->Row (y), mPixelWidth);
|
||||||
|
|
||||||
} else if (w != mPixelWidth || h != mPixelHeight) {
|
} else if (copy_required) {
|
||||||
|
|
||||||
int pw = (inSurface->Format () == pfAlpha ? 1 : 4);
|
int pw = (inSurface->Format () == pfAlpha ? 1 : 4);
|
||||||
buffer = (uint8 *)malloc (pw * mTextureWidth * mTextureHeight);
|
buffer = (uint8 *)malloc (pw * mTextureWidth * mTextureHeight);
|
||||||
|
|
||||||
for (int y = 0; y < mPixelHeight; y++) {
|
for (int y = 0; y < mPixelHeight; y++) {
|
||||||
|
|
||||||
const uint8 *src = inSurface->Row (y);
|
const uint8 *src = inSurface->Row (y);
|
||||||
uint8 *b = buffer + (mTextureWidth * pw * y);
|
uint8 *b = buffer + (mTextureWidth * pw * y);
|
||||||
memcpy (b, src, mPixelWidth * pw);
|
|
||||||
if (w > mPixelWidth)
|
if (multiplyAlpha) {
|
||||||
memcpy (b + (mPixelWidth * pw), buffer + (mPixelWidth - 1) * pw, pw);
|
|
||||||
|
for (int x = 0; x < mPixelWidth; x++) {
|
||||||
|
|
||||||
|
int a16 = multiplyAlpha[src[3]];
|
||||||
|
b[0] = (src[0] * a16) >> 16;
|
||||||
|
b[1] = (src[1] * a16) >> 16;
|
||||||
|
b[2] = (src[2] * a16) >> 16;
|
||||||
|
b[3] = src[3];
|
||||||
|
b += 4;
|
||||||
|
src += 4;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
memcpy (b, src, mPixelWidth * pw);
|
||||||
|
b += mPixelWidth * pw;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duplicate last pixel to help with bilinear interpolation
|
||||||
|
if (w > mPixelWidth)
|
||||||
|
memcpy (b, buffer + ((mPixelWidth - 1) * pw), pw);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duplicate last Row to help with bilinear interpolation
|
||||||
if (h != mPixelHeight) {
|
if (h != mPixelHeight) {
|
||||||
|
|
||||||
uint8 *b = buffer + (mTextureWidth * pw * mPixelHeight);
|
uint8 *b = buffer + (mTextureWidth * pw * mPixelHeight);
|
||||||
@@ -153,20 +198,6 @@ namespace lime {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*#ifdef LIME_PREMULTIPLIED_ALPHA
|
|
||||||
if (store_format != GL_ALPHA) {
|
|
||||||
|
|
||||||
for (int i = 0; i < mTextureWidth * mTextureHeight * 4; i += 4) {
|
|
||||||
|
|
||||||
float a = buffer[i + 3] / 255.0;
|
|
||||||
buffer[i] = int(buffer[i] * a);
|
|
||||||
buffer[i + 1] = int(buffer[i + 1] * a);
|
|
||||||
buffer[i + 2] = int(buffer[i + 2] * a);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif*/
|
|
||||||
|
|
||||||
glGenTextures (1, &mTextureID);
|
glGenTextures (1, &mTextureID);
|
||||||
// __android_log_print(ANDROID_LOG_ERROR, "lime", "CreateTexture %d (%dx%d)",
|
// __android_log_print(ANDROID_LOG_ERROR, "lime", "CreateTexture %d (%dx%d)",
|
||||||
@@ -195,7 +226,7 @@ namespace lime {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LIME_FORCE_GLES2
|
#ifndef LIME_FORCE_GLES2
|
||||||
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
//glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//int err = glGetError();
|
//int err = glGetError();
|
||||||
|
|||||||
Reference in New Issue
Block a user