mirror of
https://github.com/love2d/love.git
synced 2026-08-12 16:40:57 +02:00
244 lines
7.2 KiB
C++
244 lines
7.2 KiB
C++
/**
|
|
* Copyright (c) 2006-2026 LOVE Development Team
|
|
*
|
|
* 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.
|
|
**/
|
|
|
|
#include "renderstate.h"
|
|
#include "common/StringMap.h"
|
|
|
|
namespace love
|
|
{
|
|
namespace graphics
|
|
{
|
|
|
|
// These are all with premultiplied alpha. computeBlendState adjusts for
|
|
// alpha-multiply if needed.
|
|
static const BlendState blendStates[BLEND_MAX_ENUM] =
|
|
{
|
|
// BLEND_ALPHA
|
|
{BLENDOP_ADD, BLENDOP_ADD, BLENDFACTOR_ONE, BLENDFACTOR_ONE, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA},
|
|
|
|
// BLEND_ADD
|
|
{BLENDOP_ADD, BLENDOP_ADD, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
|
|
|
|
// BLEND_SUBTRACT
|
|
{BLENDOP_REVERSE_SUBTRACT, BLENDOP_REVERSE_SUBTRACT, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
|
|
|
|
// BLEND_MULTIPLY
|
|
{BLENDOP_ADD, BLENDOP_ADD, BLENDFACTOR_DST_COLOR, BLENDFACTOR_DST_COLOR, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO},
|
|
|
|
// BLEND_LIGHTEN
|
|
{BLENDOP_MAX, BLENDOP_MAX, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
|
|
|
|
// BLEND_DARKEN
|
|
{BLENDOP_MIN, BLENDOP_MIN, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
|
|
|
|
// BLEND_SCREEN
|
|
{BLENDOP_ADD, BLENDOP_ADD, BLENDFACTOR_ONE, BLENDFACTOR_ONE, BLENDFACTOR_ONE_MINUS_SRC_COLOR, BLENDFACTOR_ONE_MINUS_SRC_COLOR},
|
|
|
|
// BLEND_REPLACE
|
|
{BLENDOP_ADD, BLENDOP_ADD, BLENDFACTOR_ONE, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO},
|
|
|
|
// BLEND_NONE
|
|
{},
|
|
|
|
// BLEND_CUSTOM - N/A
|
|
{},
|
|
};
|
|
|
|
BlendState computeBlendState(BlendMode mode, BlendAlpha alphamode)
|
|
{
|
|
BlendState s = blendStates[mode];
|
|
|
|
// We can only do alpha-multiplication when srcRGB would have been unmodified.
|
|
if (s.srcFactorRGB == BLENDFACTOR_ONE && alphamode == BLENDALPHA_MULTIPLY && mode != BLEND_NONE)
|
|
s.srcFactorRGB = BLENDFACTOR_SRC_ALPHA;
|
|
|
|
return s;
|
|
}
|
|
|
|
BlendMode computeBlendMode(BlendState s, BlendAlpha &alphamode)
|
|
{
|
|
if (!s.enable)
|
|
{
|
|
alphamode = BLENDALPHA_PREMULTIPLIED;
|
|
return BLEND_NONE;
|
|
}
|
|
|
|
// Temporarily disable alpha multiplication when comparing to our list.
|
|
bool alphamultiply = s.srcFactorRGB == BLENDFACTOR_SRC_ALPHA;
|
|
if (alphamultiply)
|
|
s.srcFactorRGB = BLENDFACTOR_ONE;
|
|
|
|
for (int i = 0; i < (int) BLEND_MAX_ENUM; i++)
|
|
{
|
|
if (i != (int) BLEND_CUSTOM && blendStates[i] == s)
|
|
{
|
|
alphamode = alphamultiply ? BLENDALPHA_MULTIPLY : BLENDALPHA_PREMULTIPLIED;
|
|
return (BlendMode) i;
|
|
}
|
|
}
|
|
|
|
alphamode = BLENDALPHA_PREMULTIPLIED;
|
|
return BLEND_CUSTOM;
|
|
}
|
|
|
|
bool isAlphaMultiplyBlendSupported(BlendMode mode)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case BLEND_LIGHTEN:
|
|
case BLEND_DARKEN:
|
|
case BLEND_MULTIPLY:
|
|
return false;
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
static const StencilState stencilStates[STENCIL_MODE_MAX_ENUM] =
|
|
{
|
|
// STENCIL_MODE_OFF
|
|
{},
|
|
|
|
// STENCIL_MODE_DRAW
|
|
{COMPARE_ALWAYS, STENCIL_REPLACE},
|
|
|
|
// STENCIL_MODE_TEST
|
|
{COMPARE_EQUAL, STENCIL_KEEP},
|
|
|
|
// STENCIL_MODE_CUSTOM - N/A
|
|
{},
|
|
};
|
|
|
|
StencilState computeStencilState(StencilMode mode, int value)
|
|
{
|
|
StencilState s = stencilStates[mode];
|
|
s.value = value;
|
|
return s;
|
|
}
|
|
|
|
StencilMode computeStencilMode(const StencilState &s)
|
|
{
|
|
for (int i = 0; i < (int)STENCIL_MODE_MAX_ENUM; i++)
|
|
{
|
|
if (stencilStates[i].action == s.action && stencilStates[i].compare == s.compare)
|
|
return (StencilMode) i;
|
|
}
|
|
|
|
return STENCIL_MODE_CUSTOM;
|
|
}
|
|
|
|
CompareMode getReversedCompareMode(CompareMode mode)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case COMPARE_LESS: return COMPARE_GREATER;
|
|
case COMPARE_LEQUAL: return COMPARE_GEQUAL;
|
|
case COMPARE_GEQUAL: return COMPARE_LEQUAL;
|
|
case COMPARE_GREATER: return COMPARE_LESS;
|
|
default: return mode;
|
|
}
|
|
}
|
|
|
|
STRINGMAP_BEGIN(BlendMode, BLEND_MAX_ENUM, blendMode)
|
|
{
|
|
{ "alpha", BLEND_ALPHA },
|
|
{ "add", BLEND_ADD },
|
|
{ "subtract", BLEND_SUBTRACT },
|
|
{ "multiply", BLEND_MULTIPLY },
|
|
{ "lighten", BLEND_LIGHTEN },
|
|
{ "darken", BLEND_DARKEN },
|
|
{ "screen", BLEND_SCREEN },
|
|
{ "replace", BLEND_REPLACE },
|
|
{ "none", BLEND_NONE },
|
|
{ "custom", BLEND_CUSTOM },
|
|
}
|
|
STRINGMAP_END(BlendMode, BLEND_MAX_ENUM, blendMode)
|
|
|
|
STRINGMAP_BEGIN(BlendAlpha, BLENDALPHA_MAX_ENUM, blendAlpha)
|
|
{
|
|
{ "alphamultiply", BLENDALPHA_MULTIPLY },
|
|
{ "premultiplied", BLENDALPHA_PREMULTIPLIED },
|
|
}
|
|
STRINGMAP_END(BlendAlpha, BLENDALPHA_MAX_ENUM, blendAlpha)
|
|
|
|
STRINGMAP_BEGIN(BlendFactor, BLENDFACTOR_MAX_ENUM, blendFactor)
|
|
{
|
|
{ "zero", BLENDFACTOR_ZERO },
|
|
{ "one", BLENDFACTOR_ONE },
|
|
{ "srccolor", BLENDFACTOR_SRC_COLOR },
|
|
{ "oneminussrccolor", BLENDFACTOR_ONE_MINUS_SRC_COLOR },
|
|
{ "srcalpha", BLENDFACTOR_SRC_ALPHA },
|
|
{ "oneminussrcalpha", BLENDFACTOR_ONE_MINUS_SRC_ALPHA },
|
|
{ "dstcolor", BLENDFACTOR_DST_COLOR },
|
|
{ "oneminusdstcolor", BLENDFACTOR_ONE_MINUS_DST_COLOR },
|
|
{ "dstalpha", BLENDFACTOR_DST_ALPHA },
|
|
{ "oneminusdstalpha", BLENDFACTOR_ONE_MINUS_DST_ALPHA },
|
|
{ "srcalphasaturated", BLENDFACTOR_SRC_ALPHA_SATURATED },
|
|
}
|
|
STRINGMAP_END(BlendFactor, BLENDFACTOR_MAX_ENUM, blendFactor)
|
|
|
|
STRINGMAP_BEGIN(BlendOperation, BLENDOP_MAX_ENUM, blendOperation)
|
|
{
|
|
{ "add", BLENDOP_ADD },
|
|
{ "subtract", BLENDOP_SUBTRACT },
|
|
{ "reversesubtract", BLENDOP_REVERSE_SUBTRACT },
|
|
{ "min", BLENDOP_MIN },
|
|
{ "max", BLENDOP_MAX },
|
|
}
|
|
STRINGMAP_END(BlendOperation, BLENDOP_MAX_ENUM, blendOperation)
|
|
|
|
STRINGMAP_BEGIN(StencilMode, STENCIL_MODE_MAX_ENUM, stencilMode)
|
|
{
|
|
{ "off", STENCIL_MODE_OFF },
|
|
{ "draw", STENCIL_MODE_DRAW },
|
|
{ "test", STENCIL_MODE_TEST },
|
|
{ "custom", STENCIL_MODE_CUSTOM },
|
|
}
|
|
STRINGMAP_END(StencilMode, STENCIL_MODE_MAX_ENUM, stencilMode)
|
|
|
|
STRINGMAP_BEGIN(StencilAction, STENCIL_MAX_ENUM, stencilAction)
|
|
{
|
|
{ "keep", STENCIL_KEEP },
|
|
{ "zero", STENCIL_ZERO },
|
|
{ "replace", STENCIL_REPLACE },
|
|
{ "increment", STENCIL_INCREMENT },
|
|
{ "decrement", STENCIL_DECREMENT },
|
|
{ "incrementwrap", STENCIL_INCREMENT_WRAP },
|
|
{ "decrementwrap", STENCIL_DECREMENT_WRAP },
|
|
{ "invert", STENCIL_INVERT },
|
|
}
|
|
STRINGMAP_END(StencilAction, STENCIL_MAX_ENUM, stencilAction)
|
|
|
|
STRINGMAP_BEGIN(CompareMode, COMPARE_MAX_ENUM, compareMode)
|
|
{
|
|
{ "less", COMPARE_LESS },
|
|
{ "lequal", COMPARE_LEQUAL },
|
|
{ "equal", COMPARE_EQUAL },
|
|
{ "gequal", COMPARE_GEQUAL },
|
|
{ "greater", COMPARE_GREATER },
|
|
{ "notequal", COMPARE_NOTEQUAL },
|
|
{ "always", COMPARE_ALWAYS },
|
|
{ "never", COMPARE_NEVER },
|
|
}
|
|
STRINGMAP_END(CompareMode, COMPARE_MAX_ENUM, compareMode)
|
|
|
|
} // graphics
|
|
} // love
|