#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_vblank.h>
return new_color;
}
-static void alpha_blending(const u8 *argb_src, u8 *argb_dst)
+/**
+ * alpha_blend - alpha blending equation
+ * @argb_src: src pixel on premultiplied alpha mode
+ * @argb_dst: dst pixel completely opaque
+ *
+ * blend pixels using premultiplied blend formula. The current DRM assumption
+ * is that pixel color values have been already pre-multiplied with the alpha
+ * channel values. See more drm_plane_create_blend_mode_property(). Also, this
+ * formula assumes a completely opaque background.
+ */
+static void alpha_blend(const u8 *argb_src, u8 *argb_dst)
{
u8 alpha;
argb_dst[0] = blend_channel(argb_src[0], argb_dst[0], alpha);
argb_dst[1] = blend_channel(argb_src[1], argb_dst[1], alpha);
argb_dst[2] = blend_channel(argb_src[2], argb_dst[2], alpha);
- /* Opaque primary */
- argb_dst[3] = 0xFF;
+}
+
+/**
+ * x_blend - blending equation that ignores the pixel alpha
+ *
+ * overwrites RGB color value from src pixel to dst pixel.
+ */
+static void x_blend(const u8 *xrgb_src, u8 *xrgb_dst)
+{
+ memcpy(xrgb_dst, xrgb_src, sizeof(u8) * 3);
}
/**
* @vaddr_src: source address
* @dst_composer: destination framebuffer's metadata
* @src_composer: source framebuffer's metadata
+ * @pixel_blend: blending equation based on plane format
*
- * Blend the vaddr_src value with the vaddr_dst value using the pre-multiplied
- * alpha blending equation, since DRM currently assumes that the pixel color
- * values have already been pre-multiplied with the alpha channel values. See
- * more drm_plane_create_blend_mode_property(). This function uses buffer's
- * metadata to locate the new composite values at vaddr_dst.
+ * Blend the vaddr_src value with the vaddr_dst value using a pixel blend
+ * equation according to the supported plane formats DRM_FORMAT_(A/XRGB8888)
+ * and clearing alpha channel to an completely opaque background. This function
+ * uses buffer's metadata to locate the new composite values at vaddr_dst.
+ *
+ * TODO: completely clear the primary plane (a = 0xff) before starting to blend
+ * pixel color values
*/
static void blend(void *vaddr_dst, void *vaddr_src,
struct vkms_composer *dst_composer,
- struct vkms_composer *src_composer)
+ struct vkms_composer *src_composer,
+ void (*pixel_blend)(const u8 *, u8 *))
{
int i, j, j_dst, i_dst;
int offset_src, offset_dst;
pixel_src = (u8 *)(vaddr_src + offset_src);
pixel_dst = (u8 *)(vaddr_dst + offset_dst);
- alpha_blending(pixel_src, pixel_dst);
+ pixel_blend(pixel_src, pixel_dst);
+ /* clearing alpha channel (0xff)*/
+ pixel_dst[3] = 0xff;
}
i_dst++;
}
{
struct drm_gem_object *plane_obj;
struct drm_gem_shmem_object *plane_shmem_obj;
+ struct drm_framebuffer *fb = &plane_composer->fb;
+ void (*pixel_blend)(const u8 *p_src, u8 *p_dst);
plane_obj = drm_gem_fb_get_obj(&plane_composer->fb, 0);
plane_shmem_obj = to_drm_gem_shmem_obj(plane_obj);
if (WARN_ON(!plane_shmem_obj->vaddr))
return;
- blend(vaddr_out, plane_shmem_obj->vaddr,
- primary_composer, plane_composer);
+ if (fb->format->format == DRM_FORMAT_ARGB8888)
+ pixel_blend = &alpha_blend;
+ else
+ pixel_blend = &x_blend;
+
+ blend(vaddr_out, plane_shmem_obj->vaddr, primary_composer,
+ plane_composer, pixel_blend);
}
static int compose_active_planes(void **vaddr_out,