mirror of
https://github.com/X11Libre/xf86-video-vmware.git
synced 2026-03-24 01:24:37 +00:00
vmwgfx: Support xa composite.
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
This commit is contained in:
@@ -20,6 +20,7 @@ vmwgfx_drv_la_SOURCES = \
|
||||
vmwgfx_overlay.c \
|
||||
vmwgfx_ctrl.c \
|
||||
vmwgfx_ctrl.h \
|
||||
vmwgfx_xa_composite.c \
|
||||
wsbm_util.h
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "vmwgfx_saa.h"
|
||||
#include "vmwgfx_drmi.h"
|
||||
|
||||
|
||||
#define VMWGFX_PIX_MALLOC (1 << 0)
|
||||
#define VMWGFX_PIX_GMR (1 << 1)
|
||||
#define VMWGFX_PIX_SURFACE (1 << 2)
|
||||
@@ -56,6 +55,7 @@ struct vmwgfx_saa {
|
||||
Bool can_optimize_dma;
|
||||
void (*present_flush) (ScreenPtr pScreen);
|
||||
struct _WsbmListHead sync_x_list;
|
||||
struct vmwgfx_composite *vcomp;
|
||||
};
|
||||
|
||||
static inline struct vmwgfx_saa *
|
||||
@@ -276,13 +276,6 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa,
|
||||
!vpix->dirty_present)
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
* Flush dirty stuff to screen.
|
||||
*/
|
||||
|
||||
|
||||
vsaa->present_flush(vsaa->pScreen);
|
||||
|
||||
/*
|
||||
* Intersect dirty region with region to be read back, if any.
|
||||
*/
|
||||
@@ -1014,11 +1007,141 @@ vmwgfx_copy_done(struct saa_driver *driver)
|
||||
xa_copy_done(vsaa->xa_ctx);
|
||||
}
|
||||
|
||||
static Bool
|
||||
vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op,
|
||||
PicturePtr src_pict, PicturePtr mask_pict,
|
||||
PicturePtr dst_pict,
|
||||
PixmapPtr src_pix, PixmapPtr mask_pix,
|
||||
PixmapPtr dst_pix,
|
||||
RegionPtr src_region,
|
||||
RegionPtr mask_region,
|
||||
RegionPtr dst_region)
|
||||
{
|
||||
struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
|
||||
struct vmwgfx_saa_pixmap *src_vpix;
|
||||
struct vmwgfx_saa_pixmap *dst_vpix;
|
||||
struct vmwgfx_saa_pixmap *mask_vpix;
|
||||
Bool tmp_valid_hw;
|
||||
Bool dirty_hw;
|
||||
Bool valid_hw;
|
||||
RegionRec empty;
|
||||
struct xa_composite *xa_comp;
|
||||
|
||||
REGION_NULL(pScreen, &empty);
|
||||
|
||||
/*
|
||||
* First we define our migration policy. We accelerate only if there
|
||||
* is dirty hw regions to be read or if all source data is
|
||||
* available in hw, and the destination has a hardware surface.
|
||||
*/
|
||||
|
||||
dst_vpix = vmwgfx_saa_pixmap(dst_pix);
|
||||
valid_hw = (dst_vpix->hw != NULL);
|
||||
if (saa_op_reads_destination(op)) {
|
||||
vmwgfx_check_hw_contents(vsaa, dst_vpix, dst_region,
|
||||
&dirty_hw, &tmp_valid_hw);
|
||||
valid_hw = (valid_hw && tmp_valid_hw);
|
||||
} else {
|
||||
dirty_hw = FALSE;
|
||||
dst_region = ∅
|
||||
}
|
||||
|
||||
if (src_pix && !dirty_hw) {
|
||||
src_vpix = vmwgfx_saa_pixmap(src_pix);
|
||||
vmwgfx_check_hw_contents(vsaa, src_vpix, src_region,
|
||||
&dirty_hw, &tmp_valid_hw);
|
||||
valid_hw = (valid_hw && tmp_valid_hw);
|
||||
}
|
||||
|
||||
if (mask_pict && mask_pix && !dirty_hw) {
|
||||
mask_vpix = vmwgfx_saa_pixmap(mask_pix);
|
||||
vmwgfx_check_hw_contents(vsaa, mask_vpix, mask_region,
|
||||
&dirty_hw, &tmp_valid_hw);
|
||||
valid_hw = (valid_hw && tmp_valid_hw);
|
||||
}
|
||||
|
||||
if (!valid_hw && !dirty_hw)
|
||||
goto out_err;
|
||||
|
||||
/*
|
||||
* Then, setup most of the XA composite state (except hardware surfaces)
|
||||
* and check whether XA can accelerate.
|
||||
*/
|
||||
|
||||
xa_comp = vmwgfx_xa_setup_comp(vsaa->vcomp, op,
|
||||
src_pict, mask_pict, dst_pict);
|
||||
if (!xa_comp)
|
||||
goto out_err;
|
||||
|
||||
if (xa_composite_check_accelerated(xa_comp) != XA_ERR_NONE)
|
||||
goto out_err;
|
||||
|
||||
/*
|
||||
* Create hw surfaces and migrate data needed for HW compositing.
|
||||
*/
|
||||
|
||||
if (src_region == NULL)
|
||||
src_region = ∅
|
||||
if (src_pix &&
|
||||
!vmwgfx_pixmap_validate_hw(src_pix, src_region, 0, 0, 0))
|
||||
goto out_err;
|
||||
|
||||
if (mask_region == NULL)
|
||||
mask_region = ∅
|
||||
if (mask_pict && mask_pix &&
|
||||
!vmwgfx_pixmap_validate_hw(mask_pix, mask_region, 0, 0, 0))
|
||||
goto out_err;
|
||||
|
||||
if (dst_region == NULL)
|
||||
dst_region = ∅
|
||||
if (!vmwgfx_pixmap_validate_hw(dst_pix, dst_region, 0, 0, 0))
|
||||
goto out_err;
|
||||
|
||||
/*
|
||||
* Update the XA state with our hardware surfaces and
|
||||
* surface formats, and bind the XA state for compositing.
|
||||
*/
|
||||
|
||||
if (!vmwgfx_xa_update_comp(xa_comp, src_pix, mask_pix, dst_pix))
|
||||
goto out_err;
|
||||
|
||||
if (xa_composite_prepare(vsaa->xa_ctx, xa_comp))
|
||||
goto out_err;
|
||||
|
||||
REGION_UNINIT(pScreen, &empty);
|
||||
return TRUE;
|
||||
out_err:
|
||||
REGION_UNINIT(pScreen, &empty);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
vmwgfx_composite(struct saa_driver *driver,
|
||||
int src_x, int src_y, int mask_x, int mask_y,
|
||||
int dst_x, int dst_y,
|
||||
int width, int height)
|
||||
{
|
||||
struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
|
||||
|
||||
xa_composite_rect(vsaa->xa_ctx, src_x, src_y, mask_x, mask_y,
|
||||
dst_x, dst_y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
vmwgfx_composite_done(struct saa_driver *driver)
|
||||
{
|
||||
struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
|
||||
|
||||
xa_composite_done(vsaa->xa_ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
vmwgfx_takedown(struct saa_driver *driver)
|
||||
{
|
||||
struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
|
||||
|
||||
if (vsaa->vcomp)
|
||||
vmwgfx_free_composite(vsaa->vcomp);
|
||||
free(vsaa);
|
||||
}
|
||||
|
||||
@@ -1130,6 +1253,9 @@ static const struct saa_driver vmwgfx_saa_driver = {
|
||||
.copy_prepare = vmwgfx_copy_prepare,
|
||||
.copy = vmwgfx_copy,
|
||||
.copy_done = vmwgfx_copy_done,
|
||||
.composite_prepare = vmwgfx_composite_prepare,
|
||||
.composite = vmwgfx_composite,
|
||||
.composite_done = vmwgfx_composite_done,
|
||||
.takedown = vmwgfx_takedown,
|
||||
};
|
||||
|
||||
@@ -1154,6 +1280,11 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
|
||||
WSBMINITLISTHEAD(&vsaa->sync_x_list);
|
||||
|
||||
vsaa->driver = vmwgfx_saa_driver;
|
||||
vsaa->vcomp = vmwgfx_alloc_composite();
|
||||
|
||||
if (!vsaa->vcomp)
|
||||
vsaa->driver.composite_prepare = NULL;
|
||||
|
||||
if (!saa_driver_init(pScreen, &vsaa->driver))
|
||||
goto out_no_saa;
|
||||
|
||||
|
||||
@@ -29,10 +29,11 @@
|
||||
#define _VMWGFX_SAA_H_
|
||||
|
||||
#include "saa.h"
|
||||
#include <xa_tracker.h>
|
||||
#include <xa_composite.h>
|
||||
#include "vmwgfx_drmi.h"
|
||||
#include "wsbm_util.h"
|
||||
|
||||
|
||||
#define VMWGFX_FLAG_FORCE_GMR (1 << 0) /* Create with GMR as backing store */
|
||||
#define VMWGFX_FLAG_FORCE_SURFACE (1 << 1) /* Create with surface as backing store */
|
||||
#define VMWGFX_FLAG_AVOID_HWACCEL (1 << 2) /* Avoid Hardware acceleration on this pixmap */
|
||||
@@ -98,4 +99,28 @@ vmwgfx_remove_dri2_list(struct vmwgfx_saa_pixmap *vpix);
|
||||
extern void
|
||||
vmwgfx_flush_dri2(ScreenPtr pScreen);
|
||||
|
||||
/*
|
||||
* vmwgfx_xa_composite.c
|
||||
*/
|
||||
|
||||
struct vmwgfx_composite;
|
||||
|
||||
void
|
||||
vmwgfx_free_composite(struct vmwgfx_composite *vcomp);
|
||||
struct vmwgfx_composite *
|
||||
vmwgfx_alloc_composite(void);
|
||||
|
||||
Bool
|
||||
vmwgfx_xa_update_comp(struct xa_composite *comp,
|
||||
PixmapPtr src_pix,
|
||||
PixmapPtr mask_pix,
|
||||
PixmapPtr dst_pix);
|
||||
|
||||
struct xa_composite *
|
||||
vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp,
|
||||
int op,
|
||||
PicturePtr src_pict,
|
||||
PicturePtr mask_pict,
|
||||
PicturePtr dst_pict);
|
||||
|
||||
#endif
|
||||
|
||||
277
vmwgfx/vmwgfx_xa_composite.c
Normal file
277
vmwgfx/vmwgfx_xa_composite.c
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* 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 <picturestr.h>
|
||||
#include <X11/extensions/Xrender.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] = XFixedToDouble(trans->matrix[0][0]);
|
||||
matrix[3] = XFixedToDouble(trans->matrix[0][1]);
|
||||
matrix[6] = XFixedToDouble(trans->matrix[0][2]);
|
||||
|
||||
matrix[1] = XFixedToDouble(trans->matrix[1][0]);
|
||||
matrix[4] = XFixedToDouble(trans->matrix[1][1]);
|
||||
matrix[7] = XFixedToDouble(trans->matrix[1][2]);
|
||||
|
||||
matrix[2] = XFixedToDouble(trans->matrix[2][0]);
|
||||
matrix[5] = XFixedToDouble(trans->matrix[2][1]);
|
||||
matrix[8] = XFixedToDouble(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;
|
||||
}
|
||||
Reference in New Issue
Block a user