summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/amd_lx_exa.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/src/amd_lx_exa.c b/src/amd_lx_exa.c
index 107f0ea..92d5547 100644
--- a/src/amd_lx_exa.c
+++ b/src/amd_lx_exa.c
@@ -666,6 +666,19 @@ static lx_set_source_format(int srcFormat, int dstFormat)
gp_set_source_format(srcFormat);
}
+/* If we are converting colors and we need the channel A alpha,
+ * then use a special alpha type that preserves the alpha before
+ * converting the format
+ */
+
+static inline int get_op_type(struct exa_format_t *src,
+ struct exa_format_t *dst, int type)
+{
+ return (type == CIMGP_CHANNEL_A_ALPHA &&
+ src->alphabits != dst->alphabits) ?
+ CIMGP_CONVERTED_ALPHA : type;
+}
+
/* Note - this is the preferred onepass method. The other will remain
* ifdefed out until such time that we are sure its not needed
*/
@@ -677,7 +690,7 @@ lx_composite_onepass(PixmapPtr pxDst, unsigned long dstOffset,
unsigned long srcOffset, int width, int height)
{
struct blend_ops_t *opPtr;
- int apply;
+ int apply, type;
opPtr = &lx_alpha_ops[exaScratch.op * 2];
@@ -691,8 +704,10 @@ lx_composite_onepass(PixmapPtr pxDst, unsigned long dstOffset,
lx_set_source_format(exaScratch.srcFormat->fmt, exaScratch.dstFormat->fmt);
- gp_set_alpha_operation(opPtr->operation, opPtr->type, opPtr->channel,
- apply, 0);
+ type = get_op_type(exaScratch.srcFormat, exaScratch.dstFormat, opPtr->type);
+
+ gp_set_alpha_operation(opPtr->operation, type,
+ opPtr->channel, apply, 0);
gp_screen_to_screen_convert(dstOffset, srcOffset, width, height, 0);
}
@@ -706,7 +721,7 @@ lx_composite_onepass(PixmapPtr pxDst, unsigned long dstOffset,
unsigned long srcOffset, int width, int height)
{
struct blend_ops_t *opPtr;
- int apply;
+ int apply, type;
int sbpp = lx_get_bpp_from_format(exaScratch.srcFormat->fmt);
/* Copy the destination into the scratch buffer */
@@ -731,7 +746,9 @@ lx_composite_onepass(PixmapPtr pxDst, unsigned long dstOffset,
gp_declare_blt (0);
gp_set_bpp(sbpp);
- gp_set_alpha_operation(opPtr->operation, opPtr->type, opPtr->channel,
+ type = get_op_type(exaScratch.srcFormat, exaScrach.dstFormat, opPtr->type);
+
+ gp_set_alpha_operation(opPtr->operation, type, opPtr->channel,
apply, 0);
gp_set_strides(exaScratch.srcPitch, exaScratch.srcPitch);
@@ -795,7 +812,7 @@ lx_composite_multipass(PixmapPtr pxDst, unsigned long dstOffset, unsigned long s
{
struct blend_ops_t *opPtr;
int sbpp = lx_get_bpp_from_format(exaScratch.srcFormat->fmt);
- int apply;
+ int apply, type;
/* Wait until the GP is idle - this will ensure that the scratch buffer
* isn't occupied */
@@ -826,8 +843,9 @@ lx_composite_multipass(PixmapPtr pxDst, unsigned long dstOffset, unsigned long s
apply = (exaScratch.srcFormat->alphabits == 0) ?
CIMGP_APPLY_BLEND_TO_RGB : CIMGP_APPLY_BLEND_TO_ALL;
- gp_set_alpha_operation(opPtr->operation, opPtr->type, opPtr->channel,
- apply, 0);
+ /* If we're destroying the source alpha bits, then make sure we
+ * use the alpha before the color conversion
+ */
gp_screen_to_screen_blt(exaScratch.bufferOffset, srcOffset, width, height, 0);
@@ -843,7 +861,9 @@ lx_composite_multipass(PixmapPtr pxDst, unsigned long dstOffset, unsigned long s
lx_set_source_format(exaScratch.srcFormat->fmt, exaScratch.dstFormat->fmt);
- gp_set_alpha_operation(opPtr->operation, opPtr->type, opPtr->channel,
+ type = get_op_type(exaScratch.srcFormat, exaScratch.dstFormat, opPtr->type);
+
+ gp_set_alpha_operation(opPtr->operation, type, opPtr->channel,
apply, 0);
gp_screen_to_screen_convert(dstOffset, exaScratch.bufferOffset,