278 lines
7.4 KiB
C
278 lines
7.4 KiB
C
/*
|
|
* Copyright 2009-2011 VMWare, Inc.
|
|
* All Rights Reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sub license, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the
|
|
* next paragraph) shall be included in all copies or substantial portions
|
|
* of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* Author: Thomas Hellstrom <thellstrom@vmware.com>
|
|
* Author: Zack Ruzin <zackr@vmware.com>
|
|
*
|
|
* The code in this file translates XRender PICT composite stuff
|
|
* to fit the libxatracker API.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <pixman.h>
|
|
#include <picturestr.h>
|
|
#include "xa_composite.h"
|
|
#include "vmwgfx_saa.h"
|
|
#include "vmwgfx_saa_priv.h"
|
|
|
|
|
|
struct vmwgfx_composite {
|
|
union xa_source_pict *src_spict;
|
|
union xa_source_pict *mask_spict;
|
|
union xa_source_pict *dst_spict;
|
|
struct xa_picture *src_pict;
|
|
struct xa_picture *mask_pict;
|
|
struct xa_picture *dst_pict;
|
|
struct xa_composite *comp;
|
|
};
|
|
|
|
static const enum xa_composite_op vmwgfx_op_map[] = {
|
|
[PictOpClear] = xa_op_clear,
|
|
[PictOpSrc] = xa_op_src,
|
|
[PictOpDst] = xa_op_dst,
|
|
[PictOpOver] = xa_op_over,
|
|
[PictOpOverReverse] = xa_op_over_reverse,
|
|
[PictOpIn] = xa_op_in,
|
|
[PictOpInReverse] = xa_op_in_reverse,
|
|
[PictOpOut] = xa_op_out,
|
|
[PictOpOutReverse] = xa_op_out_reverse,
|
|
[PictOpAtop] = xa_op_atop,
|
|
[PictOpAtopReverse] = xa_op_atop_reverse,
|
|
[PictOpXor] = xa_op_xor,
|
|
[PictOpAdd] = xa_op_add
|
|
};
|
|
|
|
static const unsigned int vmwgfx_op_map_size =
|
|
sizeof(vmwgfx_op_map) / sizeof(enum xa_composite_op);
|
|
|
|
static Bool
|
|
vmwgfx_matrix_from_pict_transform(PictTransform *trans, float *matrix)
|
|
{
|
|
if (!trans)
|
|
return FALSE;
|
|
|
|
matrix[0] = pixman_fixed_to_double(trans->matrix[0][0]);
|
|
matrix[3] = pixman_fixed_to_double(trans->matrix[0][1]);
|
|
matrix[6] = pixman_fixed_to_double(trans->matrix[0][2]);
|
|
|
|
matrix[1] = pixman_fixed_to_double(trans->matrix[1][0]);
|
|
matrix[4] = pixman_fixed_to_double(trans->matrix[1][1]);
|
|
matrix[7] = pixman_fixed_to_double(trans->matrix[1][2]);
|
|
|
|
matrix[2] = pixman_fixed_to_double(trans->matrix[2][0]);
|
|
matrix[5] = pixman_fixed_to_double(trans->matrix[2][1]);
|
|
matrix[8] = pixman_fixed_to_double(trans->matrix[2][2]);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static enum xa_composite_wrap
|
|
vmwgfx_xa_setup_wrap(Bool pict_has_repeat, int pict_repeat)
|
|
{
|
|
enum xa_composite_wrap wrap = xa_wrap_clamp_to_border;
|
|
|
|
if (!pict_has_repeat)
|
|
return wrap;
|
|
|
|
switch(pict_repeat) {
|
|
case RepeatNormal:
|
|
wrap = xa_wrap_repeat;
|
|
break;
|
|
case RepeatReflect:
|
|
wrap = xa_wrap_mirror_repeat;
|
|
break;
|
|
case RepeatPad:
|
|
wrap = xa_wrap_clamp_to_edge;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return wrap;
|
|
}
|
|
|
|
static Bool
|
|
vmwgfx_render_filter_to_xa(int xrender_filter,
|
|
enum xa_composite_filter *out_filter)
|
|
{
|
|
switch (xrender_filter) {
|
|
case PictFilterConvolution:
|
|
case PictFilterNearest:
|
|
case PictFilterFast:
|
|
*out_filter = xa_filter_nearest;
|
|
break;
|
|
case PictFilterBest:
|
|
case PictFilterGood:
|
|
case PictFilterBilinear:
|
|
*out_filter = xa_filter_linear;
|
|
break;
|
|
default:
|
|
*out_filter = xa_filter_nearest;
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
vmwgfx_xa_setup_pict(PicturePtr pict,
|
|
struct xa_picture *xa_pict,
|
|
union xa_source_pict *src_pict)
|
|
{
|
|
if (!pict)
|
|
return FALSE;
|
|
|
|
memset(xa_pict, 0, sizeof(*xa_pict));
|
|
|
|
xa_pict->pict_format = vmwgfx_xa_format(pict->format);
|
|
if (xa_pict->pict_format == xa_format_unknown)
|
|
return FALSE;
|
|
|
|
/*
|
|
* Saa doesn't let drivers accelerate alpha maps.
|
|
*/
|
|
xa_pict->alpha_map = NULL;
|
|
xa_pict->component_alpha = pict->componentAlpha;
|
|
|
|
xa_pict->has_transform =
|
|
vmwgfx_matrix_from_pict_transform(pict->transform,
|
|
xa_pict->transform);
|
|
|
|
xa_pict->wrap = vmwgfx_xa_setup_wrap(pict->repeat,
|
|
pict->repeatType);
|
|
|
|
(void) vmwgfx_render_filter_to_xa(pict->filter, &xa_pict->filter);
|
|
|
|
if (pict->pSourcePict) {
|
|
if (pict->pSourcePict->type != SourcePictTypeSolidFill)
|
|
return FALSE;
|
|
|
|
src_pict->type = xa_src_pict_solid_fill;
|
|
src_pict->solid_fill.color = pict->pSourcePict->solidFill.color;
|
|
xa_pict->src_pict = src_pict;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
struct xa_composite *
|
|
vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp,
|
|
int op,
|
|
PicturePtr src_pict,
|
|
PicturePtr mask_pict,
|
|
PicturePtr dst_pict)
|
|
{
|
|
struct xa_composite *comp = vcomp->comp;
|
|
|
|
if (op >= vmwgfx_op_map_size)
|
|
return NULL;
|
|
|
|
comp->op = vmwgfx_op_map[op];
|
|
if (comp->op == xa_op_clear && op != PictOpClear)
|
|
return NULL;
|
|
|
|
if (!vmwgfx_xa_setup_pict(dst_pict, vcomp->dst_pict,
|
|
vcomp->dst_spict))
|
|
return NULL;
|
|
if (!vmwgfx_xa_setup_pict(src_pict, vcomp->src_pict,
|
|
vcomp->src_spict))
|
|
return NULL;
|
|
if (mask_pict && !vmwgfx_xa_setup_pict(mask_pict,
|
|
vcomp->mask_pict,
|
|
vcomp->mask_spict))
|
|
return NULL;
|
|
|
|
comp->dst = vcomp->dst_pict;
|
|
comp->src = vcomp->src_pict;
|
|
comp->mask = (mask_pict) ? vcomp->mask_pict : NULL;
|
|
|
|
return comp;
|
|
}
|
|
|
|
Bool
|
|
vmwgfx_xa_update_comp(struct xa_composite *comp,
|
|
PixmapPtr src_pix,
|
|
PixmapPtr mask_pix,
|
|
PixmapPtr dst_pix)
|
|
{
|
|
comp->dst->srf = vmwgfx_saa_pixmap(dst_pix)->hw;
|
|
if (src_pix)
|
|
comp->src->srf = vmwgfx_saa_pixmap(src_pix)->hw;
|
|
if (mask_pix && comp->mask)
|
|
comp->mask->srf = vmwgfx_saa_pixmap(mask_pix)->hw;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void
|
|
vmwgfx_free_composite(struct vmwgfx_composite *vcomp)
|
|
{
|
|
if (!vcomp)
|
|
return;
|
|
|
|
if (vcomp->src_spict)
|
|
free(vcomp->src_spict);
|
|
if (vcomp->mask_spict)
|
|
free(vcomp->mask_spict);
|
|
if (vcomp->dst_spict)
|
|
free(vcomp->dst_spict);
|
|
if (vcomp->src_pict)
|
|
free(vcomp->src_pict);
|
|
if (vcomp->mask_pict)
|
|
free(vcomp->mask_pict);
|
|
if (vcomp->dst_pict)
|
|
free(vcomp->dst_pict);
|
|
if (vcomp->comp)
|
|
free(vcomp->comp);
|
|
free(vcomp);
|
|
}
|
|
|
|
struct vmwgfx_composite *
|
|
vmwgfx_alloc_composite(void)
|
|
{
|
|
const struct xa_composite_allocation *a = xa_composite_allocation();
|
|
struct vmwgfx_composite *vcomp = calloc(1, sizeof(*vcomp));
|
|
|
|
if (!vcomp)
|
|
return NULL;
|
|
|
|
vcomp->src_spict = calloc(1, a->xa_source_pict_size);
|
|
vcomp->mask_spict = calloc(1, a->xa_source_pict_size);
|
|
vcomp->dst_spict = calloc(1, a->xa_source_pict_size);
|
|
vcomp->src_pict = calloc(1, a->xa_picture_size);
|
|
vcomp->mask_pict = calloc(1, a->xa_picture_size);
|
|
vcomp->dst_pict = calloc(1, a->xa_picture_size);
|
|
vcomp->comp = calloc(1, a->xa_composite_size);
|
|
|
|
if (!vcomp->src_spict || !vcomp->mask_spict || !vcomp->dst_spict ||
|
|
!vcomp->src_pict || !vcomp->mask_pict || !vcomp->dst_pict ||
|
|
!vcomp->comp) {
|
|
vmwgfx_free_composite(vcomp);
|
|
return NULL;
|
|
}
|
|
|
|
return vcomp;
|
|
}
|