Updates for pre-multiplied alpha (thanks Hugh)
This commit is contained in:
@@ -14,7 +14,14 @@ namespace lime {
|
||||
|
||||
|
||||
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 {
|
||||
|
||||
@@ -3036,6 +3036,30 @@ value lime_bitmap_data_height(value inHandle)
|
||||
}
|
||||
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)
|
||||
{
|
||||
Surface *surface;
|
||||
|
||||
@@ -652,6 +652,9 @@ namespace lime {
|
||||
|
||||
if (!mBase)
|
||||
return;
|
||||
if (mFlags & SURF_FLAGS_HAS_PREMULTIPLIED_ALPHA)
|
||||
return;
|
||||
|
||||
Rect r = Rect (0, 0, mWidth, mHeight);
|
||||
mVersion++;
|
||||
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;
|
||||
bool premAlpha = false;
|
||||
|
||||
if ((element.mFlags & DRAW_HAS_TEX) && element.mSurface) {
|
||||
|
||||
if (element.mSurface->GetFlags () & SURF_FLAGS_USE_PREMULTIPLIED_ALPHA) {
|
||||
|
||||
premAlpha = true;
|
||||
|
||||
}
|
||||
|
||||
progId |= PROG_TEXTURE;
|
||||
|
||||
if (element.mSurface->BytesPP () == 1) {
|
||||
|
||||
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 (lastProg) {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
namespace lime {
|
||||
|
||||
|
||||
static int *sAlpha16Table = 0;
|
||||
|
||||
bool gFullNPO2Support = 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) {
|
||||
|
||||
mPixelWidth = inSurface->Width ();
|
||||
@@ -75,7 +96,7 @@ namespace lime {
|
||||
mDirtyRect = Rect (0, 0);
|
||||
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);
|
||||
|
||||
int w = non_po2 ? mPixelWidth : UpToPower2 (mPixelWidth);
|
||||
@@ -86,7 +107,11 @@ namespace lime {
|
||||
|
||||
mTextureWidth = w;
|
||||
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;
|
||||
|
||||
@@ -96,10 +121,6 @@ namespace lime {
|
||||
int pixels = GL_UNSIGNED_BYTE;
|
||||
int gpuFormat = inSurface->GPUFormat ();
|
||||
|
||||
//if (inSurface) {
|
||||
//inSurface->multiplyAlpha();
|
||||
//}
|
||||
|
||||
if (!inSurface->GetBase ()) {
|
||||
|
||||
if (gpuFormat != fmt)
|
||||
@@ -125,20 +146,44 @@ namespace lime {
|
||||
for (int y = 0; y < mPixelHeight; y++)
|
||||
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);
|
||||
buffer = (uint8 *)malloc (pw * mTextureWidth * mTextureHeight);
|
||||
|
||||
for (int y = 0; y < mPixelHeight; y++) {
|
||||
|
||||
const uint8 *src = inSurface->Row (y);
|
||||
uint8 *b = buffer + (mTextureWidth * pw * y);
|
||||
memcpy (b, src, mPixelWidth * pw);
|
||||
|
||||
if (multiplyAlpha) {
|
||||
|
||||
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 + (mPixelWidth * pw), buffer + (mPixelWidth - 1) * pw, pw);
|
||||
memcpy (b, buffer + ((mPixelWidth - 1) * pw), pw);
|
||||
|
||||
}
|
||||
|
||||
// Duplicate last Row to help with bilinear interpolation
|
||||
if (h != 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);
|
||||
// __android_log_print(ANDROID_LOG_ERROR, "lime", "CreateTexture %d (%dx%d)",
|
||||
@@ -195,7 +226,7 @@ namespace lime {
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
//int err = glGetError();
|
||||
|
||||
Reference in New Issue
Block a user