Merge branch 'master' of 192.168.1.213:/usr/src/xf86-video-intel

This commit is contained in:
Chris Wilson 2015-06-01 08:50:31 +00:00
commit 7a371f6bef
46 changed files with 2289 additions and 791 deletions

View File

@ -523,7 +523,7 @@ void backlight_disable(struct backlight *b)
void backlight_close(struct backlight *b)
{
backlight_disable(b);
if (b->pid)
if (b->pid > 0)
waitpid(b->pid, NULL, 0);
}

View File

@ -402,6 +402,34 @@ static inline void list_move_tail(struct list *list, struct list *head)
#define container_of(ptr, type, member) \
((type *)((char *)(ptr) - (char *) &((type *)0)->member))
static inline void __list_splice(const struct list *list,
struct list *prev,
struct list *next)
{
struct list *first = list->next;
struct list *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
static inline void list_splice(const struct list *list,
struct list *head)
{
if (!list_is_empty(list))
__list_splice(list, head, head->next);
}
static inline void list_splice_tail(const struct list *list,
struct list *head)
{
if (!list_is_empty(list))
__list_splice(list, head->prev, head);
}
static inline int list_is_singular(const struct list *list)
{
return list->next == list->prev;

View File

@ -234,30 +234,36 @@ static const SymTabRec intel_chipsets[] = {
{0x0157, "HD Graphics"},
/* Broadwell Marketing names */
{0x1602, "HD graphics"},
{0x1606, "HD graphics"},
{0x160B, "HD graphics"},
{0x160A, "HD graphics"},
{0x160D, "HD graphics"},
{0x160E, "HD graphics"},
{0x1612, "HD graphics 5600"},
{0x1616, "HD graphics 5500"},
{0x161B, "HD graphics"},
{0x161A, "HD graphics"},
{0x161D, "HD graphics"},
{0x161E, "HD graphics 5300"},
{0x1622, "Iris Pro graphics 6200"},
{0x1626, "HD graphics 6000"},
{0x162B, "Iris graphics 6100"},
{0x162A, "Iris Pro graphics P6300"},
{0x162D, "HD graphics"},
{0x162E, "HD graphics"},
{0x1632, "HD graphics"},
{0x1636, "HD graphics"},
{0x163B, "HD graphics"},
{0x163A, "HD graphics"},
{0x163D, "HD graphics"},
{0x163E, "HD graphics"},
{0x1602, "HD Graphics"},
{0x1606, "HD Graphics"},
{0x160B, "HD Graphics"},
{0x160A, "HD Graphics"},
{0x160D, "HD Graphics"},
{0x160E, "HD Graphics"},
{0x1612, "HD Graphics 5600"},
{0x1616, "HD Graphics 5500"},
{0x161B, "HD Graphics"},
{0x161A, "HD Graphics"},
{0x161D, "HD Graphics"},
{0x161E, "HD Graphics 5300"},
{0x1622, "Iris Pro Graphics 6200"},
{0x1626, "HD Graphics 6000"},
{0x162B, "Iris Graphics 6100"},
{0x162A, "Iris Pro Graphics P6300"},
{0x162D, "HD Graphics"},
{0x162E, "HD Graphics"},
{0x1632, "HD Graphics"},
{0x1636, "HD Graphics"},
{0x163B, "HD Graphics"},
{0x163A, "HD Graphics"},
{0x163D, "HD Graphics"},
{0x163E, "HD Graphics"},
/* Cherryview (Cherrytrail/Braswell) */
{0x22b0, "HD Graphics"},
{0x22b1, "HD Graphics"},
{0x22b2, "HD Graphics"},
{0x22b3, "HD Graphics"},
/* When adding new identifiers, also update:
* 1. intel_identify()
@ -508,6 +514,9 @@ static enum accel_method { NOACCEL, SNA, UXA } get_accel_method(void)
if (hosted())
return SNA;
if (xf86configptr == NULL) /* X -configure */
return SNA;
dev = _xf86findDriver("intel", xf86configptr->conf_device_lst);
if (dev && dev->dev_option_lst) {
const char *s;

View File

@ -25,7 +25,6 @@ const OptionInfoRec intel_options[] = {
{OPTION_PREFER_OVERLAY, "XvPreferOverlay", OPTV_BOOLEAN, {0}, 0},
{OPTION_HOTPLUG, "HotPlug", OPTV_BOOLEAN, {0}, 1},
{OPTION_REPROBE, "ReprobeOutputs", OPTV_BOOLEAN, {0}, 0},
{OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, 0},
#ifdef INTEL_XVMC
{OPTION_XVMC, "XvMC", OPTV_BOOLEAN, {0}, 1},
#endif

View File

@ -28,7 +28,6 @@ enum intel_options {
OPTION_PREFER_OVERLAY,
OPTION_HOTPLUG,
OPTION_REPROBE,
OPTION_DELETE_DP12,
#if defined(XvMCExtension) && defined(ENABLE_XVMC)
OPTION_XVMC,
#define INTEL_XVMC 1

View File

@ -76,7 +76,7 @@ add (16) Cbn<1>F Cb<8,8,1>F -0.501961F { compr align1 };
/*
* R = Y + Cr * 1.596
*/
mov (8) acc0<1>F Yn<8,8,1>F { compr align1 };
mov (8) acc0<1>F Yn_01<8,8,1>F { compr align1 };
mac.sat(8) src_sample_r_01<1>F Crn_01<8,8,1>F 1.596F { compr align1 };
mov (8) acc0<1>F Yn_23<8,8,1>F { compr align1 };
@ -84,7 +84,7 @@ mac.sat(8) src_sample_r_23<1>F Crn_23<8,8,1>F 1.596F { compr align1 };
/*
* G = Crn * -0.813 + Cbn * -0.392 + Y
*/
mov (8) acc0<1>F Yn_23<8,8,1>F { compr align1 };
mov (8) acc0<1>F Yn_01<8,8,1>F { compr align1 };
mac (8) acc0<1>F Crn_01<8,8,1>F -0.813F { compr align1 };
mac.sat(8) src_sample_g_01<1>F Cbn_01<8,8,1>F -0.392F { compr align1 };

View File

@ -6,7 +6,7 @@
{ 0x80600048, 0x21c03ae8, 0x3e8d02c0, 0x3fcc49ba },
{ 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },
{ 0x80600048, 0x21e03ae8, 0x3e8d02e0, 0x3fcc49ba },
{ 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },
{ 0x00600001, 0x24003ae0, 0x008d0300, 0x00000000 },
{ 0x00600048, 0x24003ae0, 0x3e8d02c0, 0xbf5020c5 },
{ 0x80600048, 0x22003ae8, 0x3e8d0340, 0xbec8b439 },
{ 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },

View File

@ -976,7 +976,7 @@ memcpy_xor(const void *src, void *dst, int bpp,
}
#define BILINEAR_INTERPOLATION_BITS 4
static force_inline int
static inline int
bilinear_weight(pixman_fixed_t x)
{
return (x >> (16 - BILINEAR_INTERPOLATION_BITS)) &
@ -985,7 +985,7 @@ bilinear_weight(pixman_fixed_t x)
#if BILINEAR_INTERPOLATION_BITS <= 4
/* Inspired by Filter_32_opaque from Skia */
static force_inline uint32_t
static inline uint32_t
bilinear_interpolation(uint32_t tl, uint32_t tr,
uint32_t bl, uint32_t br,
int distx, int disty)
@ -1018,7 +1018,7 @@ bilinear_interpolation(uint32_t tl, uint32_t tr,
return ((lo >> 8) & 0xff00ff) | (hi & ~0xff00ff);
}
#elif SIZEOF_LONG > 4
static force_inline uint32_t
static inline uint32_t
bilinear_interpolation(uint32_t tl, uint32_t tr,
uint32_t bl, uint32_t br,
int distx, int disty)
@ -1063,7 +1063,7 @@ bilinear_interpolation(uint32_t tl, uint32_t tr,
return (uint32_t)(r >> 16);
}
#else
static force_inline uint32_t
static inline uint32_t
bilinear_interpolation(uint32_t tl, uint32_t tr,
uint32_t bl, uint32_t br,
int distx, int disty)

View File

@ -63,20 +63,18 @@
#define sse4_2 __attribute__((target("sse4.2,sse2,fpmath=sse")))
#endif
#if HAS_GCC(4, 7)
#define avx2 __attribute__((target("avx2,sse4.2,sse2,fpmath=sse")))
#endif
#if HAS_GCC(4, 6) && defined(__OPTIMIZE__)
#define fast __attribute__((optimize("Ofast")))
#else
#define fast
#endif
#if HAS_GCC(4, 6) && defined(__OPTIMIZE__)
#define fast_memcpy __attribute__((optimize("Ofast"))) __attribute__((target("inline-all-stringops")))
#elif HAS_GCC(4, 5) && defined(__OPTIMIZE__)
#define fast_memcpy __attribute__((target("inline-all-stringops")))
#if HAS_GCC(4, 7)
#define avx2 fast __attribute__((target("avx2,avx,sse4.2,sse2,fpmath=sse")))
#endif
#if HAS_GCC(4, 5) && defined(__OPTIMIZE__)
#define fast_memcpy fast __attribute__((target("inline-all-stringops")))
#else
#define fast_memcpy
#endif

View File

@ -52,6 +52,9 @@ inline static bool can_switch_to_blt(struct sna *sna,
if (bo && RQ_IS_BLT(bo->rq))
return true;
if (bo && bo->tiling == I915_TILING_Y)
return false;
if (sna->render_state.gt < 2)
return true;
@ -93,6 +96,9 @@ static int prefer_blt_bo(struct sna *sna,
if (src->rq)
return RQ_IS_BLT(src->rq);
if (src->tiling == I915_TILING_Y)
return false;
} else {
if (sna->render_state.gt > 2)
return false;
@ -104,7 +110,7 @@ static int prefer_blt_bo(struct sna *sna,
return dst->tiling == I915_TILING_NONE || is_uncached(sna, dst);
}
inline static bool force_blt_ring(struct sna *sna)
inline static bool force_blt_ring(struct sna *sna, struct kgem_bo *bo)
{
if (sna->kgem.mode == KGEM_RENDER)
return false;
@ -112,6 +118,9 @@ inline static bool force_blt_ring(struct sna *sna)
if (NO_RING_SWITCH(sna))
return sna->kgem.ring == KGEM_BLT;
if (bo->tiling == I915_TILING_Y)
return false;
if (sna->flags & SNA_POWERSAVE)
return true;
@ -127,7 +136,7 @@ prefer_blt_ring(struct sna *sna, struct kgem_bo *bo, unsigned flags)
if (PREFER_RENDER)
return PREFER_RENDER < 0;
assert(!force_blt_ring(sna));
assert(!force_blt_ring(sna, bo));
assert(!kgem_bo_is_render(bo) || NO_RING_SWITCH(sna));
if (kgem_bo_is_blt(bo))
@ -167,7 +176,7 @@ prefer_blt_composite(struct sna *sna, struct sna_composite_op *tmp)
untiled_tlb_miss(tmp->src.bo))
return true;
if (force_blt_ring(sna))
if (force_blt_ring(sna, tmp->dst.bo))
return true;
if (prefer_render_ring(sna, tmp->dst.bo))
@ -188,7 +197,7 @@ prefer_blt_fill(struct sna *sna, struct kgem_bo *bo, unsigned flags)
if (untiled_tlb_miss(bo))
return true;
if (force_blt_ring(sna))
if (force_blt_ring(sna, bo))
return true;
if ((flags & (FILL_POINTS | FILL_SPANS)) == 0) {

View File

@ -1965,54 +1965,77 @@ gen6_composite_set_target(struct sna *sna,
static bool
try_blt(struct sna *sna,
PicturePtr dst, PicturePtr src,
int width, int height)
uint8_t op,
PicturePtr src,
PicturePtr mask,
PicturePtr dst,
int16_t src_x, int16_t src_y,
int16_t msk_x, int16_t msk_y,
int16_t dst_x, int16_t dst_y,
int16_t width, int16_t height,
unsigned flags,
struct sna_composite_op *tmp)
{
struct kgem_bo *bo;
if (sna->kgem.mode == KGEM_BLT) {
DBG(("%s: already performing BLT\n", __FUNCTION__));
return true;
goto execute;
}
if (too_large(width, height)) {
DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
__FUNCTION__, width, height));
return true;
goto execute;
}
bo = __sna_drawable_peek_bo(dst->pDrawable);
if (bo == NULL)
return true;
goto execute;
if (untiled_tlb_miss(bo))
return true;
goto execute;
if (bo->rq)
return RQ_IS_BLT(bo->rq);
if (bo->rq) {
if (RQ_IS_BLT(bo->rq))
goto execute;
return false;
}
if (bo->tiling == I915_TILING_Y)
goto upload;
if (src->pDrawable == dst->pDrawable &&
can_switch_to_blt(sna, bo, 0))
return true;
goto execute;
if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
return true;
goto execute;
if (src->pDrawable) {
struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
if (s == NULL)
return true;
goto execute;
if (prefer_blt_bo(sna, s, bo))
return true;
goto execute;
}
if (sna->kgem.ring == KGEM_BLT) {
DBG(("%s: already performing BLT\n", __FUNCTION__));
return true;
goto execute;
}
return false;
upload:
flags |= COMPOSITE_UPLOAD;
execute:
return sna_blt_composite(sna, op,
src, dst,
src_x, src_y,
dst_x, dst_y,
width, height,
flags, tmp);
}
static bool
@ -2242,13 +2265,13 @@ gen6_render_composite(struct sna *sna,
width, height, sna->kgem.ring));
if (mask == NULL &&
try_blt(sna, dst, src, width, height) &&
sna_blt_composite(sna, op,
src, dst,
src_x, src_y,
dst_x, dst_y,
width, height,
flags, tmp))
try_blt(sna, op,
src, mask, dst,
src_x, src_y,
msk_x, msk_y,
dst_x, dst_y,
width, height,
flags, tmp))
return true;
if (gen6_composite_fallback(sna, src, mask, dst))
@ -2695,7 +2718,7 @@ static inline bool prefer_blt_copy(struct sna *sna,
untiled_tlb_miss(dst_bo))
return true;
if (force_blt_ring(sna))
if (force_blt_ring(sna, dst_bo))
return true;
if (kgem_bo_is_render(dst_bo) ||

View File

@ -2184,55 +2184,78 @@ gen7_composite_set_target(struct sna *sna,
static bool
try_blt(struct sna *sna,
PicturePtr dst, PicturePtr src,
int width, int height)
uint8_t op,
PicturePtr src,
PicturePtr mask,
PicturePtr dst,
int16_t src_x, int16_t src_y,
int16_t msk_x, int16_t msk_y,
int16_t dst_x, int16_t dst_y,
int16_t width, int16_t height,
unsigned flags,
struct sna_composite_op *tmp)
{
struct kgem_bo *bo;
if (sna->kgem.mode == KGEM_BLT) {
DBG(("%s: already performing BLT\n", __FUNCTION__));
return true;
goto execute;
}
if (too_large(width, height)) {
DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
__FUNCTION__, width, height));
return true;
goto execute;
}
bo = __sna_drawable_peek_bo(dst->pDrawable);
if (bo == NULL)
return true;
goto execute;
if (untiled_tlb_miss(bo))
return true;
goto execute;
if (bo->rq)
return RQ_IS_BLT(bo->rq);
if (bo->rq) {
if (RQ_IS_BLT(bo->rq))
goto execute;
return false;
}
if (bo->tiling == I915_TILING_Y)
goto upload;
if (src->pDrawable == dst->pDrawable &&
(sna->render_state.gt < 3 || width*height < 1024) &&
can_switch_to_blt(sna, bo, 0))
return true;
goto execute;
if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
return true;
goto execute;
if (src->pDrawable) {
struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
if (s == NULL)
return true;
goto upload;
if (prefer_blt_bo(sna, s, bo))
return true;
goto execute;
}
if (sna->kgem.ring == KGEM_BLT) {
DBG(("%s: already performing BLT\n", __FUNCTION__));
return true;
goto execute;
}
return false;
upload:
flags |= COMPOSITE_UPLOAD;
execute:
return sna_blt_composite(sna, op,
src, dst,
src_x, src_y,
dst_x, dst_y,
width, height,
flags, tmp);
}
static bool
@ -2462,13 +2485,13 @@ gen7_render_composite(struct sna *sna,
width, height, sna->kgem.mode, sna->kgem.ring));
if (mask == NULL &&
try_blt(sna, dst, src, width, height) &&
sna_blt_composite(sna, op,
src, dst,
src_x, src_y,
dst_x, dst_y,
width, height,
flags, tmp))
try_blt(sna, op,
src, mask, dst,
src_x, src_y,
msk_x, msk_y,
dst_x, dst_y,
width, height,
flags, tmp))
return true;
if (gen7_composite_fallback(sna, src, mask, dst))
@ -2893,7 +2916,7 @@ prefer_blt_copy(struct sna *sna,
if (flags & COPY_DRI && !sna->kgem.has_semaphores)
return false;
if (force_blt_ring(sna))
if (force_blt_ring(sna, dst_bo))
return true;
if ((flags & COPY_SMALL ||

View File

@ -205,6 +205,33 @@ static const struct blendinfo {
#define OUT_VERTEX(x,y) vertex_emit_2s(sna, x,y)
#define OUT_VERTEX_F(v) vertex_emit(sna, v)
struct gt_info {
const char *name;
struct {
int max_vs_entries;
} urb;
};
static const struct gt_info bdw_gt_info = {
.name = "Broadwell (gen8)",
.urb = { .max_vs_entries = 960 },
};
static bool is_bdw(struct sna *sna)
{
return sna->kgem.gen == 0100;
}
static const struct gt_info chv_gt_info = {
.name = "Cherryview (gen8)",
.urb = { .max_vs_entries = 640 },
};
static bool is_chv(struct sna *sna)
{
return sna->kgem.gen == 0101;
}
static inline bool too_large(int width, int height)
{
return width > GEN8_MAX_SIZE || height > GEN8_MAX_SIZE;
@ -462,7 +489,7 @@ gen8_emit_urb(struct sna *sna)
{
/* num of VS entries must be divisible by 8 if size < 9 */
OUT_BATCH(GEN8_3DSTATE_URB_VS | (2 - 2));
OUT_BATCH(960 << URB_ENTRY_NUMBER_SHIFT |
OUT_BATCH(sna->render_state.gen8.info->urb.max_vs_entries << URB_ENTRY_NUMBER_SHIFT |
(2 - 1) << URB_ENTRY_SIZE_SHIFT |
4 << URB_STARTING_ADDRESS_SHIFT);
@ -2002,55 +2029,78 @@ gen8_composite_set_target(struct sna *sna,
static bool
try_blt(struct sna *sna,
PicturePtr dst, PicturePtr src,
int width, int height)
uint8_t op,
PicturePtr src,
PicturePtr mask,
PicturePtr dst,
int16_t src_x, int16_t src_y,
int16_t msk_x, int16_t msk_y,
int16_t dst_x, int16_t dst_y,
int16_t width, int16_t height,
unsigned flags,
struct sna_composite_op *tmp)
{
struct kgem_bo *bo;
if (sna->kgem.mode == KGEM_BLT) {
DBG(("%s: already performing BLT\n", __FUNCTION__));
return true;
goto execute;
}
if (too_large(width, height)) {
DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
__FUNCTION__, width, height));
return true;
goto execute;
}
bo = __sna_drawable_peek_bo(dst->pDrawable);
if (bo == NULL)
return true;
goto execute;
if (untiled_tlb_miss(bo))
return true;
goto execute;
if (bo->rq)
return RQ_IS_BLT(bo->rq);
if (bo->rq) {
if (RQ_IS_BLT(bo->rq))
goto execute;
return false;
}
if (bo->tiling == I915_TILING_Y)
goto upload;
if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
return true;
goto execute;
if (src->pDrawable == dst->pDrawable &&
(sna->render_state.gt < 3 || width*height < 1024) &&
can_switch_to_blt(sna, bo, 0))
return true;
goto execute;
if (src->pDrawable) {
struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
if (s == NULL)
return true;
goto upload;
if (prefer_blt_bo(sna, s, bo))
return true;
goto execute;
}
if (sna->kgem.ring == KGEM_BLT) {
DBG(("%s: already performing BLT\n", __FUNCTION__));
return true;
goto execute;
}
return false;
upload:
flags |= COMPOSITE_UPLOAD;
execute:
return sna_blt_composite(sna, op,
src, dst,
src_x, src_y,
dst_x, dst_y,
width, height,
flags, tmp);
}
static bool
@ -2280,13 +2330,13 @@ gen8_render_composite(struct sna *sna,
width, height, sna->kgem.mode, sna->kgem.ring));
if (mask == NULL &&
try_blt(sna, dst, src, width, height) &&
sna_blt_composite(sna, op,
src, dst,
src_x, src_y,
dst_x, dst_y,
width, height,
flags, tmp))
try_blt(sna, op,
src, mask, dst,
src_x, src_y,
msk_x, msk_y,
dst_x, dst_y,
width, height,
flags, tmp))
return true;
if (gen8_composite_fallback(sna, src, mask, dst))
@ -2716,7 +2766,7 @@ prefer_blt_copy(struct sna *sna,
if (flags & COPY_DRI && !sna->kgem.has_semaphores)
return false;
if (force_blt_ring(sna))
if (force_blt_ring(sna, dst_bo))
return true;
if ((flags & COPY_SMALL ||
@ -3915,6 +3965,13 @@ static bool gen8_render_setup(struct sna *sna)
state->gt = ((devid >> 4) & 0xf) + 1;
DBG(("%s: gt=%d\n", __FUNCTION__, state->gt));
if (is_bdw(sna))
state->info = &bdw_gt_info;
else if (is_chv(sna))
state->info = &chv_gt_info;
else
return false;
sna_static_stream_init(&general);
/* Zero pad the start. If you see an offset of 0x0 in the batchbuffer
@ -4026,5 +4083,5 @@ const char *gen8_render_init(struct sna *sna, const char *backend)
sna->render.max_3d_size = GEN8_MAX_SIZE;
sna->render.max_3d_pitch = 1 << 18;
return "Broadwell";
return sna->render_state.gen8.info->name;
}

File diff suppressed because it is too large Load Diff

View File

@ -158,6 +158,8 @@ struct kgem {
int16_t count;
} vma[NUM_MAP_TYPES];
uint32_t bcs_state;
uint32_t batch_flags;
uint32_t batch_flags_base;
#define I915_EXEC_SECURE (1<<9)
@ -188,7 +190,9 @@ struct kgem {
uint32_t has_handle_lut :1;
uint32_t has_wc_mmap :1;
uint32_t can_fence :1;
uint32_t can_blt_cpu :1;
uint32_t can_blt_y :1;
uint32_t can_render_y :1;
uint32_t can_scanout_y :1;
@ -232,7 +236,7 @@ struct kgem {
#define KGEM_MAX_DEFERRED_VBO 16
#define KGEM_BATCH_RESERVED 1
#define KGEM_BATCH_RESERVED 8 /* LRI(SWCTRL) + END */
#define KGEM_RELOC_RESERVED (KGEM_MAX_DEFERRED_VBO)
#define KGEM_EXEC_RESERVED (1+KGEM_MAX_DEFERRED_VBO)
@ -407,7 +411,7 @@ static inline void kgem_set_mode(struct kgem *kgem,
enum kgem_mode mode,
struct kgem_bo *bo)
{
assert(!kgem->wedged);
warn_unless(!kgem->wedged);
#if DEBUG_FLUSH_BATCH
kgem_submit(kgem);
@ -429,7 +433,7 @@ static inline void _kgem_set_mode(struct kgem *kgem, enum kgem_mode mode)
{
assert(kgem->mode == KGEM_NONE);
assert(kgem->nbatch == 0);
assert(!kgem->wedged);
warn_unless(!kgem->wedged);
kgem->context_switch(kgem, mode);
kgem->mode = mode;
}
@ -573,7 +577,7 @@ static inline bool kgem_bo_can_blt(struct kgem *kgem,
{
assert(bo->refcnt);
if (bo->tiling == I915_TILING_Y) {
if (bo->tiling == I915_TILING_Y && !kgem->can_blt_y) {
DBG(("%s: can not blt to handle=%d, tiling=Y\n",
__FUNCTION__, bo->handle));
return false;
@ -588,6 +592,22 @@ static inline bool kgem_bo_can_blt(struct kgem *kgem,
return kgem_bo_blt_pitch_is_ok(kgem, bo);
}
void __kgem_bcs_set_tiling(struct kgem *kgem,
struct kgem_bo *src,
struct kgem_bo *dst);
inline static void kgem_bcs_set_tiling(struct kgem *kgem,
struct kgem_bo *src,
struct kgem_bo *dst)
{
assert(kgem->mode == KGEM_BLT);
if (!kgem->can_blt_y)
return;
__kgem_bcs_set_tiling(kgem, src, dst);
}
static inline bool kgem_bo_is_snoop(struct kgem_bo *bo)
{
assert(bo->refcnt);

View File

@ -248,7 +248,6 @@ struct sna {
#define SNA_FLUSH_GTT 0x400
#define SNA_PERFORMANCE 0x1000
#define SNA_POWERSAVE 0x2000
#define SNA_REMOVE_OUTPUTS 0x4000
#define SNA_HAS_FLIP 0x10000
#define SNA_HAS_ASYNC_FLIP 0x20000
#define SNA_LINEAR_FB 0x40000
@ -323,7 +322,8 @@ struct sna {
uint32_t fg, bg;
int size;
int active;
bool disable;
bool active;
int last_x;
int last_y;
@ -591,13 +591,51 @@ static inline void sna_present_vblank_handler(struct drm_event_vblank *event) {
#endif
extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation);
extern int sna_crtc_to_pipe(xf86CrtcPtr crtc);
extern int sna_crtc_to_pipe__safe(xf86CrtcPtr crtc);
extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc);
extern uint32_t sna_crtc_id(xf86CrtcPtr crtc);
extern bool sna_crtc_is_on(xf86CrtcPtr crtc);
extern bool sna_crtc_is_transformed(xf86CrtcPtr crtc);
#define CRTC_VBLANK 0x3
#define CRTC_ON 0x80000000
static inline unsigned long *sna_crtc_flags(xf86CrtcPtr crtc)
{
unsigned long *flags = crtc->driver_private;
assert(flags);
return flags;
}
static inline unsigned sna_crtc_pipe(xf86CrtcPtr crtc)
{
return *sna_crtc_flags(crtc) >> 8 & 0xff;
}
static inline unsigned sna_crtc_id(xf86CrtcPtr crtc)
{
return *sna_crtc_flags(crtc) >> 16 & 0xff;
}
static inline bool sna_crtc_is_on(xf86CrtcPtr crtc)
{
return *sna_crtc_flags(crtc) & CRTC_ON;
}
static inline void sna_crtc_set_vblank(xf86CrtcPtr crtc)
{
assert((*sna_crtc_flags(crtc) & CRTC_VBLANK) < 2);
++*sna_crtc_flags(crtc);
}
static inline void sna_crtc_clear_vblank(xf86CrtcPtr crtc)
{
assert(*sna_crtc_flags(crtc) & CRTC_VBLANK);
--*sna_crtc_flags(crtc);
}
static inline bool sna_crtc_has_vblank(xf86CrtcPtr crtc)
{
return *sna_crtc_flags(crtc) & CRTC_VBLANK;
}
CARD32 sna_format_for_depth(int depth);
CARD32 sna_render_format_for_depth(int depth);

View File

@ -67,7 +67,8 @@
#define FORCE_FLUSH 0
#define FORCE_FULL_SYNC 0 /* https://bugs.freedesktop.org/show_bug.cgi?id=61628 */
#define DEFAULT_TILING I915_TILING_X
#define DEFAULT_PIXMAP_TILING I915_TILING_X
#define DEFAULT_SCANOUT_TILING I915_TILING_X
#define USE_INPLACE 1
#define USE_SPANS 0 /* -1 force CPU, 1 force GPU */
@ -613,9 +614,9 @@ static bool sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv, bool a
static inline uint32_t default_tiling(struct sna *sna, PixmapPtr pixmap)
{
#if DEFAULT_TILING == I915_TILING_NONE
#if DEFAULT_PIXMAP_TILING == I915_TILING_NONE
return I915_TILING_NONE;
#elif DEFAULT_TILING == I915_TILING_X
#elif DEFAULT_PIXMAP_TILING == I915_TILING_X
return I915_TILING_X;
#else
/* Try to avoid hitting the Y-tiling GTT mapping bug on 855GM */
@ -631,15 +632,6 @@ static inline uint32_t default_tiling(struct sna *sna, PixmapPtr pixmap)
pixmap->drawable.height > sna->render.max_3d_size))
return I915_TILING_X;
if (sna_damage_is_all(&sna_pixmap(pixmap)->cpu_damage,
pixmap->drawable.width,
pixmap->drawable.height)) {
DBG(("%s: entire source is damaged, using Y-tiling\n",
__FUNCTION__));
sna_damage_destroy(&sna_pixmap(priv)->gpu_damage);
return I915_TILING_Y;
}
return I915_TILING_Y;
#endif
}
@ -691,6 +683,12 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
return NULL;
}
if (bo->tiling == priv->gpu_bo->tiling) {
DBG(("%s: tiling request failed\n", __FUNCTION__));
kgem_bo_destroy(&sna->kgem, bo);
return NULL;
}
box.x1 = box.y1 = 0;
box.x2 = pixmap->drawable.width;
box.y2 = pixmap->drawable.height;
@ -825,8 +823,8 @@ create_pixmap(struct sna *sna, ScreenPtr screen,
datasize += adjust;
}
DBG(("%s: allocating pixmap %dx%d, depth=%d, size=%ld\n",
__FUNCTION__, width, height, depth, (long)datasize));
DBG(("%s: allocating pixmap %dx%d, depth=%d/%d, size=%ld\n",
__FUNCTION__, width, height, depth, bpp, (long)datasize));
pixmap = AllocatePixmap(screen, datasize);
if (!pixmap)
return NullPixmap;
@ -1648,7 +1646,7 @@ static bool sna_pixmap_alloc_gpu(struct sna *sna,
if (pixmap->usage_hint == SNA_CREATE_FB && (sna->flags & SNA_LINEAR_FB) == 0) {
flags |= CREATE_SCANOUT;
tiling = kgem_choose_tiling(&sna->kgem,
-I915_TILING_X,
-DEFAULT_SCANOUT_TILING,
pixmap->drawable.width,
pixmap->drawable.height,
pixmap->drawable.bitsPerPixel);
@ -2373,21 +2371,26 @@ skip_inplace_map:
assert(pixmap->devPrivate.ptr == MAP(priv->cpu_bo->map__cpu));
}
assert(pixmap->devKind);
if (priv->clear_color == 0 ||
pixmap->drawable.bitsPerPixel == 8 ||
priv->clear_color == (1 << pixmap->drawable.depth) - 1) {
memset(pixmap->devPrivate.ptr, priv->clear_color,
(size_t)pixmap->devKind * pixmap->drawable.height);
} else {
pixman_fill(pixmap->devPrivate.ptr,
pixmap->devKind/sizeof(uint32_t),
pixmap->drawable.bitsPerPixel,
0, 0,
pixmap->drawable.width,
pixmap->drawable.height,
priv->clear_color);
}
if (sigtrap_get() == 0) {
assert(pixmap->devKind);
sigtrap_assert_active();
if (priv->clear_color == 0 ||
pixmap->drawable.bitsPerPixel == 8 ||
priv->clear_color == (1 << pixmap->drawable.depth) - 1) {
memset(pixmap->devPrivate.ptr, priv->clear_color,
(size_t)pixmap->devKind * pixmap->drawable.height);
} else {
pixman_fill(pixmap->devPrivate.ptr,
pixmap->devKind/sizeof(uint32_t),
pixmap->drawable.bitsPerPixel,
0, 0,
pixmap->drawable.width,
pixmap->drawable.height,
priv->clear_color);
}
sigtrap_put();
} else
return false;
clear_done:
sna_damage_all(&priv->cpu_damage, pixmap);
@ -2936,17 +2939,22 @@ move_to_cpu:
assert(pixmap->devPrivate.ptr == MAP(priv->cpu_bo->map__cpu));
}
assert(pixmap->devKind);
do {
pixman_fill(pixmap->devPrivate.ptr,
pixmap->devKind/sizeof(uint32_t),
pixmap->drawable.bitsPerPixel,
box->x1, box->y1,
box->x2 - box->x1,
box->y2 - box->y1,
priv->clear_color);
box++;
} while (--n);
if (sigtrap_get() == 0) {
assert(pixmap->devKind);
sigtrap_assert_active();
do {
pixman_fill(pixmap->devPrivate.ptr,
pixmap->devKind/sizeof(uint32_t),
pixmap->drawable.bitsPerPixel,
box->x1, box->y1,
box->x2 - box->x1,
box->y2 - box->y1,
priv->clear_color);
box++;
} while (--n);
sigtrap_put();
} else
return false;
clear_done:
if (flags & MOVE_WRITE ||
@ -4089,7 +4097,7 @@ sna_pixmap_create_upload(ScreenPtr screen,
assert(width);
assert(height);
if (depth == 1)
if (depth < 8)
return create_pixmap(sna, screen, width, height, depth,
CREATE_PIXMAP_USAGE_SCRATCH);
@ -5297,6 +5305,7 @@ sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
assert(kgem_bo_can_blt(&sna->kgem, bo));
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
/* Region is pre-clipped and translated into pixmap space */
box = region_rects(region);
@ -5318,6 +5327,7 @@ sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
upload = kgem_create_buffer(&sna->kgem,
bstride*bh,
@ -5461,6 +5471,7 @@ sna_put_xypixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
assert(kgem_bo_can_blt(&sna->kgem, bo));
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
skip = h * BitmapBytePad(w + left);
for (i = 1 << (gc->depth-1); i; i >>= 1, bits += skip) {
@ -5488,6 +5499,7 @@ sna_put_xypixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
upload = kgem_create_buffer(&sna->kgem,
bstride*bh,
@ -6871,18 +6883,22 @@ fallback:
return;
}
assert(dst_pixmap->devPrivate.ptr);
assert(dst_pixmap->devKind);
do {
pixman_fill(dst_pixmap->devPrivate.ptr,
dst_pixmap->devKind/sizeof(uint32_t),
dst_pixmap->drawable.bitsPerPixel,
box->x1, box->y1,
box->x2 - box->x1,
box->y2 - box->y1,
src_priv->clear_color);
box++;
} while (--n);
if (sigtrap_get() == 0) {
assert(dst_pixmap->devPrivate.ptr);
assert(dst_pixmap->devKind);
sigtrap_assert_active();
do {
pixman_fill(dst_pixmap->devPrivate.ptr,
dst_pixmap->devKind/sizeof(uint32_t),
dst_pixmap->drawable.bitsPerPixel,
box->x1, box->y1,
box->x2 - box->x1,
box->y2 - box->y1,
src_priv->clear_color);
box++;
} while (--n);
sigtrap_put();
}
} else if (!sna_copy_boxes__inplace(sna, region, alu,
src_pixmap, src_priv,
src_dx, src_dy,
@ -6939,36 +6955,39 @@ fallback:
((char *)src_pixmap->devPrivate.ptr +
src_dy * src_stride + src_dx * bpp / 8);
do {
DBG(("%s: memcpy_blt(box=(%d, %d), (%d, %d), src=(%d, %d), pitches=(%d, %d))\n",
__FUNCTION__,
box->x1, box->y1,
box->x2 - box->x1,
box->y2 - box->y1,
src_dx, src_dy,
src_stride, dst_stride));
if (sigtrap_get() == 0) {
do {
DBG(("%s: memcpy_blt(box=(%d, %d), (%d, %d), src=(%d, %d), pitches=(%d, %d))\n",
__FUNCTION__,
box->x1, box->y1,
box->x2 - box->x1,
box->y2 - box->y1,
src_dx, src_dy,
src_stride, dst_stride));
assert(box->x1 >= 0);
assert(box->y1 >= 0);
assert(box->x2 <= dst_pixmap->drawable.width);
assert(box->y2 <= dst_pixmap->drawable.height);
assert(box->x1 >= 0);
assert(box->y1 >= 0);
assert(box->x2 <= dst_pixmap->drawable.width);
assert(box->y2 <= dst_pixmap->drawable.height);
assert(box->x1 + src_dx >= 0);
assert(box->y1 + src_dy >= 0);
assert(box->x2 + src_dx <= src_pixmap->drawable.width);
assert(box->y2 + src_dy <= src_pixmap->drawable.height);
assert(has_coherent_ptr(sna, src_priv, MOVE_READ));
assert(has_coherent_ptr(sna, dst_priv, MOVE_WRITE));
assert(src_stride);
assert(dst_stride);
memcpy_blt(src_bits, dst_bits, bpp,
src_stride, dst_stride,
box->x1, box->y1,
box->x1, box->y1,
box->x2 - box->x1,
box->y2 - box->y1);
box++;
} while (--n);
assert(box->x1 + src_dx >= 0);
assert(box->y1 + src_dy >= 0);
assert(box->x2 + src_dx <= src_pixmap->drawable.width);
assert(box->y2 + src_dy <= src_pixmap->drawable.height);
assert(has_coherent_ptr(sna, src_priv, MOVE_READ));
assert(has_coherent_ptr(sna, dst_priv, MOVE_WRITE));
assert(src_stride);
assert(dst_stride);
memcpy_blt(src_bits, dst_bits, bpp,
src_stride, dst_stride,
box->x1, box->y1,
box->x1, box->y1,
box->x2 - box->x1,
box->y2 - box->y1);
box++;
} while (--n);
sigtrap_put();
}
} else {
DBG(("%s: fallback -- miCopyRegion\n", __FUNCTION__));
@ -8341,6 +8360,7 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
return; /* XXX fallback? */
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, arg->bo);
assert(sna->kgem.mode == KGEM_BLT);
if (sna->kgem.gen >= 0100) {
@ -8408,6 +8428,7 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
return; /* XXX fallback? */
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, arg->bo);
upload = kgem_create_buffer(&sna->kgem,
bstride*bh,
@ -8558,6 +8579,7 @@ sna_copy_plane_blt(DrawablePtr source, DrawablePtr drawable, GCPtr gc,
return; /* XXX fallback? */
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, arg->bo);
upload = kgem_create_buffer(&sna->kgem,
bstride*bh,
@ -8674,6 +8696,8 @@ sna_copy_plane_blt(DrawablePtr source, DrawablePtr drawable, GCPtr gc,
}
}
kgem_bcs_set_tiling(&sna->kgem, upload, arg->bo);
assert(sna->kgem.mode == KGEM_BLT);
b = sna->kgem.batch + sna->kgem.nbatch;
if (sna->kgem.gen >= 0100) {
@ -12283,6 +12307,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
get_drawable_deltas(drawable, pixmap, &dx, &dy);
assert(extents->x1 + dx >= 0);
@ -12426,6 +12451,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
_kgem_submit(&sna->kgem);
_kgem_set_mode(&sna->kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
} while (1);
} else {
RegionRec clip;
@ -12494,6 +12520,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
if (!kgem_check_batch(&sna->kgem, 3)) {
_kgem_submit(&sna->kgem);
_kgem_set_mode(&sna->kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
unwind_batch = sna->kgem.nbatch;
unwind_reloc = sna->kgem.nreloc;
@ -12590,6 +12617,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
DBG(("%s: emitting split batch\n", __FUNCTION__));
_kgem_submit(&sna->kgem);
_kgem_set_mode(&sna->kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
unwind_batch = sna->kgem.nbatch;
unwind_reloc = sna->kgem.nreloc;
@ -13219,6 +13247,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
if (!clipped) {
dx += drawable->x;
@ -13331,6 +13360,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
_kgem_submit(&sna->kgem);
_kgem_set_mode(&sna->kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
} while (1);
} else {
RegionRec clip;
@ -13388,6 +13418,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
if (!kgem_check_batch(&sna->kgem, 3)) {
_kgem_submit(&sna->kgem);
_kgem_set_mode(&sna->kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
assert(sna->kgem.mode == KGEM_BLT);
b = sna->kgem.batch + sna->kgem.nbatch;
@ -13460,6 +13491,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
if (!kgem_check_batch(&sna->kgem, 3)) {
_kgem_submit(&sna->kgem);
_kgem_set_mode(&sna->kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
assert(sna->kgem.mode == KGEM_BLT);
b = sna->kgem.batch + sna->kgem.nbatch;
@ -13590,6 +13622,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
get_drawable_deltas(drawable, pixmap, &dx, &dy);
kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
assert(kgem_bo_can_blt(&sna->kgem, bo));
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
br00 = 3 << 20;
br13 = bo->pitch;
@ -13634,6 +13667,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
assert(sna->kgem.mode == KGEM_BLT);
b = sna->kgem.batch + sna->kgem.nbatch;
@ -13697,6 +13731,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
upload = kgem_create_buffer(&sna->kgem,
bstride*bh,
@ -13827,6 +13862,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
assert(sna->kgem.mode == KGEM_BLT);
b = sna->kgem.batch + sna->kgem.nbatch;
@ -13888,6 +13924,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
upload = kgem_create_buffer(&sna->kgem,
bstride*bh,
@ -14018,6 +14055,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
assert(sna->kgem.mode == KGEM_BLT);
b = sna->kgem.batch + sna->kgem.nbatch;
@ -14078,6 +14116,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
upload = kgem_create_buffer(&sna->kgem,
bstride*bh,
@ -14217,6 +14256,7 @@ sna_poly_fill_rect_stippled_n_box__imm(struct sna *sna,
return; /* XXX fallback? */
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
assert(sna->kgem.mode == KGEM_BLT);
b = sna->kgem.batch + sna->kgem.nbatch;
@ -14342,6 +14382,7 @@ sna_poly_fill_rect_stippled_n_box(struct sna *sna,
return; /* XXX fallback? */
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
assert(sna->kgem.mode == KGEM_BLT);
b = sna->kgem.batch + sna->kgem.nbatch;
@ -14505,6 +14546,7 @@ sna_poly_fill_rect_stippled_n_blt__imm(DrawablePtr drawable,
get_drawable_deltas(drawable, pixmap, &dx, &dy);
kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
assert(kgem_bo_can_blt(&sna->kgem, bo));
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
br00 = XY_MONO_SRC_COPY_IMM | 3 << 20;
br13 = bo->pitch;
@ -14650,6 +14692,7 @@ sna_poly_fill_rect_stippled_n_blt(DrawablePtr drawable,
get_drawable_deltas(drawable, pixmap, &dx, &dy);
kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
assert(kgem_bo_can_blt(&sna->kgem, bo));
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
br00 = XY_MONO_SRC_COPY | 3 << 20;
br13 = bo->pitch;
@ -15372,6 +15415,7 @@ sna_glyph_blt(DrawablePtr drawable, GCPtr gc,
}
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
DBG(("%s: glyph clip box (%d, %d), (%d, %d)\n",
__FUNCTION__,
@ -15459,6 +15503,7 @@ sna_glyph_blt(DrawablePtr drawable, GCPtr gc,
if (!kgem_check_batch(&sna->kgem, 3+len)) {
_kgem_submit(&sna->kgem);
_kgem_set_mode(&sna->kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
DBG(("%s: new batch, glyph clip box (%d, %d), (%d, %d)\n",
__FUNCTION__,
@ -16093,6 +16138,7 @@ sna_reversed_glyph_blt(DrawablePtr drawable, GCPtr gc,
}
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
unwind_batch = sna->kgem.nbatch;
unwind_reloc = sna->kgem.nreloc;
@ -16202,6 +16248,7 @@ sna_reversed_glyph_blt(DrawablePtr drawable, GCPtr gc,
if (!kgem_check_batch(&sna->kgem, 3+len)) {
_kgem_submit(&sna->kgem);
_kgem_set_mode(&sna->kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
unwind_batch = sna->kgem.nbatch;
unwind_reloc = sna->kgem.nreloc;
@ -16541,6 +16588,7 @@ sna_push_pixels_solid_blt(GCPtr gc,
kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
assert(kgem_bo_can_blt(&sna->kgem, bo));
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
/* Region is pre-clipped and translated into pixmap space */
box = region_rects(region);
@ -16562,6 +16610,7 @@ sna_push_pixels_solid_blt(GCPtr gc,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
upload = kgem_create_buffer(&sna->kgem,
bstride*bh,
@ -17029,7 +17078,7 @@ sna_get_image__fast(PixmapPtr pixmap,
if (priv == NULL || priv->gpu_damage == NULL)
return false;
if (priv->clear) {
if (priv->clear && sigtrap_get() == 0) {
int w = region->extents.x2 - region->extents.x1;
int h = region->extents.y2 - region->extents.y1;
int pitch = PixmapBytePad(w, pixmap->drawable.depth);
@ -17038,6 +17087,7 @@ sna_get_image__fast(PixmapPtr pixmap,
__FUNCTION__, priv->clear_color));
assert(DAMAGE_IS_ALL(priv->gpu_damage));
assert(priv->cpu_damage == NULL);
sigtrap_assert_active();
if (priv->clear_color == 0 ||
pixmap->drawable.bitsPerPixel == 8 ||
@ -17054,6 +17104,7 @@ sna_get_image__fast(PixmapPtr pixmap,
priv->clear_color);
}
sigtrap_put();
return true;
}

View File

@ -86,6 +86,11 @@ static const uint8_t fill_ROP[] = {
ROP_1
};
static void sig_done(struct sna *sna, const struct sna_composite_op *op)
{
sigtrap_put();
}
static void nop_done(struct sna *sna, const struct sna_composite_op *op)
{
assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem));
@ -129,7 +134,6 @@ static bool sna_blt_fill_init(struct sna *sna,
struct kgem *kgem = &sna->kgem;
assert(kgem_bo_can_blt (kgem, bo));
assert(bo->tiling != I915_TILING_Y);
blt->bo[0] = bo;
blt->br13 = bo->pitch;
@ -183,6 +187,7 @@ static bool sna_blt_fill_init(struct sna *sna,
return false;
_kgem_set_mode(kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(kgem, NULL, bo);
assert(sna->kgem.mode == KGEM_BLT);
b = kgem->batch + kgem->nbatch;
@ -243,6 +248,8 @@ noinline static void __sna_blt_fill_begin(struct sna *sna,
struct kgem *kgem = &sna->kgem;
uint32_t *b;
kgem_bcs_set_tiling(&sna->kgem, NULL, blt->bo[0]);
assert(kgem->mode == KGEM_BLT);
b = kgem->batch + kgem->nbatch;
if (sna->kgem.gen >= 0100) {
@ -295,6 +302,7 @@ inline static void sna_blt_fill_begin(struct sna *sna,
if (kgem->nreloc) {
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(kgem, NULL, blt->bo[0]);
assert(kgem->nbatch == 0);
}
@ -338,8 +346,8 @@ static bool sna_blt_copy_init(struct sna *sna,
{
struct kgem *kgem = &sna->kgem;
assert(kgem_bo_can_blt (kgem, src));
assert(kgem_bo_can_blt (kgem, dst));
assert(kgem_bo_can_blt(kgem, src));
assert(kgem_bo_can_blt(kgem, dst));
blt->bo[0] = src;
blt->bo[1] = dst;
@ -378,6 +386,7 @@ static bool sna_blt_copy_init(struct sna *sna,
return false;
_kgem_set_mode(kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, src, dst);
sna->blt_state.fill_bo = 0;
return true;
@ -432,6 +441,7 @@ static bool sna_blt_alpha_fixup_init(struct sna *sna,
return false;
_kgem_set_mode(kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, src, dst);
sna->blt_state.fill_bo = 0;
return true;
@ -462,6 +472,7 @@ static void sna_blt_alpha_fixup_one(struct sna *sna,
!kgem_check_reloc(kgem, 2)) {
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, blt->bo[0], blt->bo[1]);
}
assert(sna->kgem.mode == KGEM_BLT);
@ -590,6 +601,7 @@ static void sna_blt_copy_one(struct sna *sna,
!kgem_check_reloc(kgem, 2)) {
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, blt->bo[0], blt->bo[1]);
}
assert(sna->kgem.mode == KGEM_BLT);
@ -998,6 +1010,7 @@ static void blt_composite_fill__cpu(struct sna *sna,
assert(op->dst.pixmap->devPrivate.ptr);
assert(op->dst.pixmap->devKind);
sigtrap_assert_active();
pixman_fill(op->dst.pixmap->devPrivate.ptr,
op->dst.pixmap->devKind / sizeof(uint32_t),
op->dst.pixmap->drawable.bitsPerPixel,
@ -1017,6 +1030,7 @@ blt_composite_fill_box_no_offset__cpu(struct sna *sna,
assert(op->dst.pixmap->devPrivate.ptr);
assert(op->dst.pixmap->devKind);
sigtrap_assert_active();
pixman_fill(op->dst.pixmap->devPrivate.ptr,
op->dst.pixmap->devKind / sizeof(uint32_t),
op->dst.pixmap->drawable.bitsPerPixel,
@ -1037,6 +1051,7 @@ blt_composite_fill_boxes_no_offset__cpu(struct sna *sna,
assert(op->dst.pixmap->devPrivate.ptr);
assert(op->dst.pixmap->devKind);
sigtrap_assert_active();
pixman_fill(op->dst.pixmap->devPrivate.ptr,
op->dst.pixmap->devKind / sizeof(uint32_t),
op->dst.pixmap->drawable.bitsPerPixel,
@ -1058,6 +1073,7 @@ blt_composite_fill_box__cpu(struct sna *sna,
assert(op->dst.pixmap->devPrivate.ptr);
assert(op->dst.pixmap->devKind);
sigtrap_assert_active();
pixman_fill(op->dst.pixmap->devPrivate.ptr,
op->dst.pixmap->devKind / sizeof(uint32_t),
op->dst.pixmap->drawable.bitsPerPixel,
@ -1079,6 +1095,7 @@ blt_composite_fill_boxes__cpu(struct sna *sna,
assert(op->dst.pixmap->devPrivate.ptr);
assert(op->dst.pixmap->devKind);
sigtrap_assert_active();
pixman_fill(op->dst.pixmap->devPrivate.ptr,
op->dst.pixmap->devKind / sizeof(uint32_t),
op->dst.pixmap->drawable.bitsPerPixel,
@ -1431,6 +1448,7 @@ begin_blt(struct sna *sna,
return false;
_kgem_set_mode(&sna->kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, NULL, op->dst.bo);
}
return true;
@ -1456,6 +1474,7 @@ prepare_blt_clear(struct sna *sna,
DBG(("%s\n", __FUNCTION__));
if (op->dst.bo == NULL) {
op->u.blt.pixel = 0;
op->blt = blt_composite_fill__cpu;
if (op->dst.x|op->dst.y) {
op->box = blt_composite_fill_box__cpu;
@ -1466,9 +1485,8 @@ prepare_blt_clear(struct sna *sna,
op->boxes = blt_composite_fill_boxes_no_offset__cpu;
op->thread_boxes = blt_composite_fill_boxes_no_offset__cpu;
}
op->done = nop_done;
op->u.blt.pixel = 0;
return true;
op->done = sig_done;
return sigtrap_get() == 0;
}
op->blt = blt_composite_fill;
@ -1511,8 +1529,8 @@ prepare_blt_fill(struct sna *sna,
op->boxes = blt_composite_fill_boxes_no_offset__cpu;
op->thread_boxes = blt_composite_fill_boxes_no_offset__cpu;
}
op->done = nop_done;
return true;
op->done = sig_done;
return sigtrap_get() == 0;
}
op->blt = blt_composite_fill;
@ -1695,6 +1713,7 @@ static void blt_composite_copy_boxes__thread(struct sna *sna,
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
} while (1);
} else {
do {
@ -1751,6 +1770,7 @@ static void blt_composite_copy_boxes__thread(struct sna *sna,
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
} while (1);
}
sna_vertex_unlock(&sna->render);
@ -1833,6 +1853,7 @@ static void blt_composite_copy_boxes__thread64(struct sna *sna,
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
} while (1);
} else {
do {
@ -1891,6 +1912,7 @@ static void blt_composite_copy_boxes__thread64(struct sna *sna,
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
} while (1);
}
sna_vertex_unlock(&sna->render);
@ -2000,6 +2022,7 @@ prepare_blt_copy(struct sna *sna,
}
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, bo, op->dst.bo);
DBG(("%s\n", __FUNCTION__));
@ -2423,6 +2446,9 @@ prepare_blt_put(struct sna *sna,
op->box = blt_put_composite_box;
op->boxes = blt_put_composite_boxes;
}
op->done = nop_done;
return true;
} else {
if (alpha_fixup) {
op->u.blt.pixel = alpha_fixup;
@ -2434,10 +2460,10 @@ prepare_blt_put(struct sna *sna,
op->box = blt_put_composite_box__cpu;
op->boxes = blt_put_composite_boxes__cpu;
}
}
op->done = nop_done;
return true;
op->done = sig_done;
return sigtrap_get() == 0;
}
}
static bool
@ -2594,6 +2620,8 @@ clear:
}
if (hint & REPLACES)
kgem_bo_undo(&sna->kgem, tmp->dst.bo);
if (flags & COMPOSITE_UPLOAD)
return false;
} else {
RegionRec region;
@ -2680,6 +2708,8 @@ fill:
}
if (hint & REPLACES)
kgem_bo_undo(&sna->kgem, tmp->dst.bo);
if (flags & COMPOSITE_UPLOAD)
return false;
} else {
RegionRec region;
@ -2818,7 +2848,7 @@ fill:
if (src_pixmap->drawable.width <= sna->render.max_3d_size &&
src_pixmap->drawable.height <= sna->render.max_3d_size &&
bo->pitch <= sna->render.max_3d_pitch &&
(flags & COMPOSITE_FALLBACK) == 0)
(flags & (COMPOSITE_UPLOAD | COMPOSITE_FALLBACK)) == 0)
{
return false;
}
@ -2869,7 +2899,7 @@ fallback:
DBG(("%s: fallback -- unaccelerated upload\n",
__FUNCTION__));
goto fallback;
} else {
} else if ((flags & COMPOSITE_UPLOAD) == 0) {
ret = prepare_blt_copy(sna, tmp, bo, alpha_fixup);
if (!ret)
goto fallback;
@ -3046,6 +3076,7 @@ sna_blt_composite__convert(struct sna *sna,
}
_kgem_set_mode(&sna->kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, tmp->src.bo, tmp->dst.bo);
if (alpha_fixup) {
tmp->blt = blt_composite_copy_with_alpha;
@ -3387,6 +3418,7 @@ static bool sna_blt_fill_box(struct sna *sna, uint8_t alu,
_kgem_set_mode(kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
assert(kgem_check_batch(kgem, 6));
assert(kgem_check_reloc(kgem, 1));
@ -3493,6 +3525,8 @@ bool sna_blt_fill_boxes(struct sna *sna, uint8_t alu,
_kgem_set_mode(kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
assert(sna->kgem.mode == KGEM_BLT);
b = kgem->batch + kgem->nbatch;
if (kgem->gen >= 0100) {
@ -3581,6 +3615,7 @@ bool sna_blt_fill_boxes(struct sna *sna, uint8_t alu,
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
assert(sna->kgem.mode == KGEM_BLT);
b = kgem->batch + kgem->nbatch;
@ -3727,6 +3762,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
}
_kgem_set_mode(kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
if ((dst_dx | dst_dy) == 0) {
if (kgem->gen >= 0100) {
@ -3787,6 +3823,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
} while (1);
} else {
uint64_t hdr = (uint64_t)br13 << 32 | cmd | 6;
@ -3844,6 +3881,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
} while (1);
}
} else {
@ -3905,6 +3943,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
} while (1);
} else {
cmd |= 6;
@ -3962,6 +4001,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
} while (1);
}
}
@ -4068,6 +4108,7 @@ bool sna_blt_copy_boxes__with_alpha(struct sna *sna, uint8_t alu,
!kgem_check_reloc(kgem, 2)) {
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
}
assert(sna->kgem.mode == KGEM_BLT);
@ -4163,6 +4204,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
DBG(("%s: dst == src\n", __FUNCTION__));
if (src_bo->tiling == I915_TILING_Y &&
!sna->kgem.can_blt_y &&
kgem_bo_blt_pitch_is_ok(&sna->kgem, src_bo)) {
struct kgem_bo *bo;
@ -4210,6 +4252,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
}
} else {
if (src_bo->tiling == I915_TILING_Y &&
!sna->kgem.can_blt_y &&
kgem_bo_blt_pitch_is_ok(&sna->kgem, src_bo)) {
DBG(("%s: src is y-tiled\n", __FUNCTION__));
if (src->type != DRAWABLE_PIXMAP)
@ -4224,6 +4267,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
}
if (dst_bo->tiling == I915_TILING_Y &&
!sna->kgem.can_blt_y &&
kgem_bo_blt_pitch_is_ok(&sna->kgem, dst_bo)) {
DBG(("%s: dst is y-tiled\n", __FUNCTION__));
if (dst->type != DRAWABLE_PIXMAP)

File diff suppressed because it is too large Load Diff

View File

@ -400,6 +400,9 @@ static uint32_t color_tiling(struct sna *sna, DrawablePtr draw)
{
uint32_t tiling;
if (!sna->kgem.can_fence)
return I915_TILING_NONE;
if (COLOR_PREFER_TILING_Y &&
(draw->width != sna->front->drawable.width ||
draw->height != sna->front->drawable.height))
@ -427,7 +430,6 @@ static struct kgem_bo *sna_pixmap_set_dri(struct sna *sna,
PixmapPtr pixmap)
{
struct sna_pixmap *priv;
int tiling;
DBG(("%s: attaching DRI client to pixmap=%ld\n",
__FUNCTION__, pixmap->drawable.serialNumber));
@ -451,11 +453,18 @@ static struct kgem_bo *sna_pixmap_set_dri(struct sna *sna,
assert(priv->gpu_bo->proxy == NULL);
assert(priv->gpu_bo->flush == false);
tiling = color_tiling(sna, &pixmap->drawable);
if (tiling < 0)
tiling = -tiling;
if (priv->gpu_bo->tiling != tiling && !priv->gpu_bo->scanout)
sna_pixmap_change_tiling(pixmap, tiling);
if (!sna->kgem.can_fence) {
if (!sna_pixmap_change_tiling(pixmap, I915_TILING_NONE)) {
DBG(("%s: failed to discard tiling (%d) for DRI2 protocol\n", __FUNCTION__, priv->gpu_bo->tiling));
return NULL;
}
} else {
int tiling = color_tiling(sna, &pixmap->drawable);
if (tiling < 0)
tiling = -tiling;
if (priv->gpu_bo->tiling < tiling && !priv->gpu_bo->scanout)
sna_pixmap_change_tiling(pixmap, tiling);
}
return priv->gpu_bo;
}
@ -870,6 +879,22 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
}
}
#if defined(__GNUC__)
#define popcount(x) __builtin_popcount(x)
#else
static int popcount(unsigned int x)
{
int count = 0;
while (x) {
count += x&1;
x >>= 1;
}
return count;
}
#endif
static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kgem_bo *src, bool sync)
{
struct drm_i915_gem_busy busy;
@ -940,9 +965,12 @@ static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kg
* The ultimate question is whether preserving the ring outweighs
* the cost of the query.
*/
mode = KGEM_RENDER;
if (busy.busy & (0xfffe << 16))
if (popcount(busy.busy >> 16) > 1)
mode = busy.busy & 0xffff ? KGEM_BLT : KGEM_RENDER;
else if (busy.busy & (0xfffe << 16))
mode = KGEM_BLT;
else
mode = KGEM_RENDER;
kgem_bo_mark_busy(&sna->kgem, busy.handle == src->handle ? src : dst, mode);
_kgem_set_mode(&sna->kgem, mode);
}
@ -1312,8 +1340,8 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc)
const struct ust_msc *this = sna_crtc_last_swap(crtc);
DBG(("%s: Window transferring from pipe=%d [msc=%llu] to pipe=%d [msc=%llu], delta now %lld\n",
__FUNCTION__,
sna_crtc_to_pipe(priv->crtc), (long long)last->msc,
sna_crtc_to_pipe(crtc), (long long)this->msc,
sna_crtc_pipe(priv->crtc), (long long)last->msc,
sna_crtc_pipe(crtc), (long long)this->msc,
(long long)(priv->msc_delta + this->msc - last->msc)));
priv->msc_delta += this->msc - last->msc;
priv->crtc = crtc;
@ -1491,7 +1519,7 @@ sna_dri2_add_event(struct sna *sna,
info->sna = sna;
info->draw = draw;
info->crtc = crtc;
info->pipe = sna_crtc_to_pipe(crtc);
info->pipe = sna_crtc_pipe(crtc);
if (!add_event_to_client(info, sna, client)) {
free(info);
@ -1685,7 +1713,7 @@ can_flip(struct sna * sna,
}
if (!sna_crtc_is_on(crtc)) {
DBG(("%s: ref-pipe=%d is disabled\n", __FUNCTION__, sna_crtc_to_pipe(crtc)));
DBG(("%s: ref-pipe=%d is disabled\n", __FUNCTION__, sna_crtc_pipe(crtc)));
return false;
}
@ -2137,7 +2165,7 @@ static void fake_swap_complete(struct sna *sna, ClientPtr client,
swap = sna_crtc_last_swap(crtc);
DBG(("%s(type=%d): draw=%ld, pipe=%d, frame=%lld [msc %lld], tv=%d.%06d\n",
__FUNCTION__, type, (long)draw->id, crtc ? sna_crtc_to_pipe(crtc) : -1,
__FUNCTION__, type, (long)draw->id, crtc ? sna_crtc_pipe(crtc) : -1,
(long long)swap->msc,
(long long)draw_current_msc(draw, crtc, swap->msc),
swap->tv_sec, swap->tv_usec));
@ -2587,7 +2615,7 @@ get_current_msc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr crtc)
VG_CLEAR(vbl);
vbl.request.type = _DRM_VBLANK_RELATIVE;
vbl.request.sequence = 0;
if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(crtc)) == 0)
if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(crtc)) == 0)
ret = sna_crtc_record_vblank(crtc, &vbl);
else
ret = sna_crtc_last_swap(crtc)->msc;
@ -2704,7 +2732,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
if (immediate) {
info = sna->dri2.flip_pending;
DBG(("%s: performing immediate swap on pipe %d, pending? %d, mode: %d, continuation? %d\n",
__FUNCTION__, sna_crtc_to_pipe(crtc),
__FUNCTION__, sna_crtc_pipe(crtc),
info != NULL, info ? info->flip_continue : 0,
info && info->draw == draw));
@ -2844,7 +2872,7 @@ sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
DBG(("%s: synchronous?=%d, send-event?=%d\n", __FUNCTION__, sync, event));
if (!sync || event) {
DBG(("%s: performing immediate xchg on pipe %d\n",
__FUNCTION__, sna_crtc_to_pipe(crtc)));
__FUNCTION__, sna_crtc_pipe(crtc)));
sna_dri2_xchg(draw, front, back);
}
if (sync) {
@ -2906,7 +2934,7 @@ sna_dri2_schedule_xchg_crtc(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc
DBG(("%s: synchronous?=%d, send-event?=%d\n", __FUNCTION__, sync, event));
if (!sync || event) {
DBG(("%s: performing immediate xchg only on pipe %d\n",
__FUNCTION__, sna_crtc_to_pipe(crtc)));
__FUNCTION__, sna_crtc_pipe(crtc)));
sna_dri2_xchg_crtc(sna, draw, crtc, front, back);
}
if (sync) {
@ -3173,7 +3201,7 @@ sna_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
const struct ust_msc *swap;
DBG(("%s(draw=%ld, pipe=%d)\n", __FUNCTION__, draw->id,
crtc ? sna_crtc_to_pipe(crtc) : -1));
crtc ? sna_crtc_pipe(crtc) : -1));
if (crtc != NULL) {
union drm_wait_vblank vbl;
@ -3181,7 +3209,7 @@ sna_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
VG_CLEAR(vbl);
vbl.request.type = _DRM_VBLANK_RELATIVE;
vbl.request.sequence = 0;
if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(crtc)) == 0)
if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(crtc)) == 0)
sna_crtc_record_vblank(crtc, &vbl);
} else
/* Drawable not displayed, make up a *monotonic* value */
@ -3215,7 +3243,7 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
crtc = sna_dri2_get_crtc(draw);
DBG(("%s(pipe=%d, target_msc=%llu, divisor=%llu, rem=%llu)\n",
__FUNCTION__, crtc ? sna_crtc_to_pipe(crtc) : -1,
__FUNCTION__, crtc ? sna_crtc_pipe(crtc) : -1,
(long long)target_msc,
(long long)divisor,
(long long)remainder));
@ -3224,7 +3252,7 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
if (crtc == NULL)
goto out_complete;
pipe = sna_crtc_to_pipe(crtc);
pipe = sna_crtc_pipe(crtc);
VG_CLEAR(vbl);

View File

@ -270,6 +270,8 @@ static PixmapPtr sna_dri3_pixmap_from_fd(ScreenPtr screen,
priv->ptr = MAKE_STATIC_PTR(pixmap->devPrivate.ptr);
} else {
assert(priv->gpu_bo == bo);
priv->create = kgem_can_create_2d(&sna->kgem,
width, height, depth);
priv->pinned |= PIN_DRI3;
}
list_add(&priv->cow_list, &sna->dri3.pixmaps);
@ -325,6 +327,15 @@ static int sna_dri3_fd_from_pixmap(ScreenPtr screen,
return -1;
}
if (bo->tiling && !sna->kgem.can_fence) {
if (!sna_pixmap_change_tiling(pixmap, I915_TILING_NONE)) {
DBG(("%s: unable to discard GPU tiling (%d) for DRI3 protocol\n",
__FUNCTION__, bo->tiling));
return -1;
}
bo = priv->gpu_bo;
}
fd = kgem_bo_export_to_prime(&sna->kgem, bo);
if (fd == -1) {
DBG(("%s: exporting handle=%d to fd failed\n", __FUNCTION__, bo->handle));

View File

@ -199,7 +199,7 @@ sna_set_fallback_mode(ScrnInfoPtr scrn)
#endif
}
static Bool sna_set_desired_mode(struct sna *sna)
static void sna_set_desired_mode(struct sna *sna)
{
ScrnInfoPtr scrn = sna->scrn;
@ -212,7 +212,6 @@ static Bool sna_set_desired_mode(struct sna *sna)
}
sna_mode_check(sna);
return TRUE;
}
/**
@ -282,7 +281,7 @@ static Bool sna_create_screen_resources(ScreenPtr screen)
if (serverGeneration == 1 && (sna->flags & SNA_IS_HOSTED) == 0)
sna_copy_fbcon(sna);
(void)sna_set_desired_mode(sna);
sna_set_desired_mode(sna);
}
return TRUE;
@ -620,9 +619,8 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int probe)
if (xf86ReturnOptValBool(sna->Options, OPTION_TILING_FB, FALSE))
sna->flags |= SNA_LINEAR_FB;
if (xf86ReturnOptValBool(sna->Options, OPTION_DELETE_DP12, FALSE))
sna->flags |= SNA_REMOVE_OUTPUTS;
if (!sna->kgem.can_fence)
sna->flags |= SNA_LINEAR_FB;
if (!xf86ReturnOptValBool(sna->Options, OPTION_SWAPBUFFERS_WAIT, TRUE))
sna->flags |= SNA_NO_WAIT;
@ -1220,13 +1218,8 @@ static Bool sna_enter_vt(VT_FUNC_ARGS_DECL)
sna_mode_discover(sna);
sna->flags &= ~SNA_REPROBE;
}
sna_mode_check(sna);
if (!sna_set_desired_mode(sna)) {
sna_accel_leave(sna);
intel_put_master(sna->dev);
return FALSE;
}
sna_set_desired_mode(sna);
return TRUE;
}

View File

@ -74,7 +74,7 @@
#define NO_GLYPHS_VIA_MASK 0
#define FORCE_SMALL_MASK 0 /* -1 = never, 1 = always */
#define NO_GLYPHS_SLOW 0
#define NO_DISCARD_MASK 0
#define DISCARD_MASK 0 /* -1 = never, 1 = always */
#define CACHE_PICTURE_SIZE 1024
#define GLYPH_MIN_SIZE 8
@ -1094,6 +1094,9 @@ sna_glyph_get_image(GlyphPtr g, ScreenPtr s)
static inline bool use_small_mask(struct sna *sna, int16_t width, int16_t height, int depth)
{
if (depth < 8)
return true;
if (FORCE_SMALL_MASK)
return FORCE_SMALL_MASK > 0;
@ -1156,12 +1159,6 @@ glyphs_via_mask(struct sna *sna,
src_x += box.x1 - list->xOff;
src_y += box.y1 - list->yOff;
if (format->depth < 8) {
format = PictureMatchFormat(screen, 8, PICT_a8);
if (!format)
return false;
}
component_alpha = NeedsComponent(format->format);
if (use_small_mask(sna, width, height, format->depth)) {
pixman_image_t *mask_image;
@ -1179,7 +1176,7 @@ use_small_mask:
return false;
mask_image =
pixman_image_create_bits(format->depth << 24 | format->format,
pixman_image_create_bits(pixmap->drawable.bitsPerPixel << 24 | format->format,
width, height,
pixmap->devPrivate.ptr,
pixmap->devKind);
@ -1386,10 +1383,11 @@ next_image:
DBG(("%s: atlas format=%08x, mask format=%08x\n",
__FUNCTION__,
(int)p->atlas->format,
(int)(format->depth << 24 | format->format)));
(int)mask->format));
memset(&tmp, 0, sizeof(tmp));
if (p->atlas->format == (format->depth << 24 | format->format)) {
if (p->atlas->format == mask->format ||
alphaless(p->atlas->format) == mask->format) {
ok = sna->render.composite(sna, PictOpAdd,
p->atlas, NULL, mask,
0, 0, 0, 0, 0, 0,
@ -1564,6 +1562,8 @@ skip_glyph:
out:
if (list_extents != stack_extents)
free(list_extents);
DBG(("%s: format=%08d, depth=%d\n",
__FUNCTION__, format->format, format->depth));
return format;
}
@ -1573,24 +1573,34 @@ static bool can_discard_mask(uint8_t op, PicturePtr src, PictFormatPtr mask,
PictFormatPtr g;
uint32_t color;
if (NO_DISCARD_MASK)
return false;
if (DISCARD_MASK)
return DISCARD_MASK > 0;
DBG(("%s: nlist=%d, mask=%08x, depth %d, op=%d (bounded? %d)\n",
__FUNCTION__, nlist,
mask ? (unsigned)mask->format : 0, mask ? mask->depth : 0,
op, op_is_bounded(op)));
if (nlist == 1 && list->len == 1)
return true;
if (nlist == 1 && list->len == 1) {
if (mask == list->format)
return true;
if (!op_is_bounded(op))
g = list->format;
goto skip;
}
if (!op_is_bounded(op)) {
DBG(("%s: unbounded op, not discarding\n", __FUNCTION__));
return false;
}
/* No glyphs overlap and we are not performing a mask conversion. */
g = glyphs_format(nlist, list, glyphs);
if (mask == g)
if (mask == g) {
DBG(("%s: mask matches glyphs format, no conversion, so discard mask\n",
__FUNCTION__));
return true;
}
DBG(("%s: preferred mask format %08x, depth %d\n",
__FUNCTION__, g ? (unsigned)g->format : 0, g ? g->depth : 0));
@ -1605,18 +1615,41 @@ static bool can_discard_mask(uint8_t op, PicturePtr src, PictFormatPtr mask,
list++;
}
if (!sna_picture_is_solid(src, &color))
return false;
return color >> 24 == 0xff;
} else {
if (PICT_FORMAT_A(mask->format) >= PICT_FORMAT_A(g->format))
skip:
if (mask->format == g->format)
return true;
if (g->depth != 1)
return false;
}
if (mask->format == alphaless(g->format))
return true;
if (PICT_FORMAT_TYPE(g->format) == PICT_TYPE_A &&
PICT_FORMAT_TYPE(mask->format) != PICT_TYPE_A)
return true;
if (!sna_picture_is_solid(src, &color))
return false;
}
}
return color >> 24 == 0xff;
static uint32_t pixman_format(PictFormatPtr short_format)
{
uint32_t bpp;
bpp = short_format->depth;
if (bpp <= 1)
bpp = 1;
else if (bpp <= 8)
bpp = 8;
else if (bpp <= 16)
bpp = 16;
else
bpp = 32;
return bpp << 24 | short_format->format;
}
static void
@ -1756,7 +1789,7 @@ next:
if (sigtrap_get() == 0) {
if (mask_format) {
pixman_composite_glyphs(op, src_image, dst_image,
mask_format->format | (mask_format->depth << 24),
pixman_format(mask_format),
src_x + src_dx + region.extents.x1 - dst_x,
src_y + src_dy + region.extents.y1 - dst_y,
region.extents.x1, region.extents.y1,
@ -1815,10 +1848,10 @@ out:
x, y,
mask_format->depth,
(long)mask_format->format,
(long)(mask_format->depth << 24 | mask_format->format),
(long)pixman_format(mask_format),
NeedsComponent(mask_format->format)));
mask_image =
pixman_image_create_bits(mask_format->depth << 24 | mask_format->format,
pixman_image_create_bits(pixman_format(mask_format),
region.extents.x2 - region.extents.x1,
region.extents.y2 - region.extents.y1,
NULL, 0);
@ -2086,12 +2119,6 @@ glyphs_via_image(struct sna *sna,
src_x += box.x1 - list->xOff;
src_y += box.y1 - list->yOff;
if (format->depth < 8) {
format = PictureMatchFormat(screen, 8, PICT_a8);
if (!format)
return false;
}
DBG(("%s: small mask [format=%lx, depth=%d, size=%d], rendering glyphs to upload buffer\n",
__FUNCTION__, (unsigned long)format->format,
format->depth, (uint32_t)width*height*format->depth));
@ -2104,7 +2131,7 @@ glyphs_via_image(struct sna *sna,
return false;
mask_image =
pixman_image_create_bits(format->depth << 24 | format->format,
pixman_image_create_bits(pixmap->drawable.bitsPerPixel << 24 | format->format,
width, height,
pixmap->devPrivate.ptr,
pixmap->devKind);

View File

@ -105,8 +105,10 @@ read_boxes_inplace__cpu(struct kgem *kgem,
if (!download_inplace__cpu(kgem, dst, bo, box, n))
return false;
if (bo->tiling == I915_TILING_Y)
return false;
assert(kgem_bo_can_map__cpu(kgem, bo, false));
assert(bo->tiling != I915_TILING_Y);
src = kgem_bo_map__cpu(kgem, bo);
if (src == NULL)
@ -281,6 +283,9 @@ fallback:
if (box[n].y2 > extents.y2)
extents.y2 = box[n].y2;
}
if (!can_blt && sna->render.max_3d_size == 0)
goto fallback;
if (kgem_bo_can_map(kgem, src_bo)) {
/* Is it worth detiling? */
if ((extents.y2 - extents.y1 - 1) * src_bo->pitch < 4096)
@ -477,6 +482,7 @@ fallback:
goto fallback;
_kgem_set_mode(kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, src_bo, NULL);
tmp_nbox = nbox;
tmp_box = box;
@ -539,6 +545,7 @@ fallback:
break;
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, src_bo, NULL);
tmp_box += nbox_this_time;
} while (1);
} else {
@ -597,6 +604,7 @@ fallback:
break;
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, src_bo, NULL);
tmp_box += nbox_this_time;
} while (1);
}
@ -666,8 +674,10 @@ write_boxes_inplace__tiled(struct kgem *kgem,
{
uint8_t *dst;
if (bo->tiling == I915_TILING_Y)
return false;
assert(kgem->has_wc_mmap || kgem_bo_can_map__cpu(kgem, bo, true));
assert(bo->tiling != I915_TILING_Y);
if (kgem_bo_can_map__cpu(kgem, bo, true)) {
dst = kgem_bo_map__cpu(kgem, bo);
@ -849,6 +859,8 @@ bool sna_write_boxes(struct sna *sna, PixmapPtr dst,
if (box[n].y2 > extents.y2)
extents.y2 = box[n].y2;
}
if (!can_blt && sna->render.max_3d_size == 0)
goto fallback;
/* Try to avoid switching rings... */
if (!can_blt || kgem->ring == KGEM_RENDER ||
@ -1038,6 +1050,7 @@ tile:
goto fallback;
_kgem_set_mode(kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
if (kgem->gen >= 0100) {
cmd |= 8;
@ -1129,6 +1142,7 @@ tile:
if (nbox) {
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
}
kgem_bo_destroy(kgem, src_bo);
@ -1224,6 +1238,7 @@ tile:
if (nbox) {
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
}
kgem_bo_destroy(kgem, src_bo);
@ -1541,6 +1556,7 @@ tile:
goto fallback;
_kgem_set_mode(kgem, KGEM_BLT);
}
kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
if (sna->kgem.gen >= 0100) {
cmd |= 8;
@ -1636,6 +1652,7 @@ tile:
if (nbox) {
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
}
kgem_bo_destroy(kgem, src_bo);
@ -1732,6 +1749,7 @@ tile:
if (nbox) {
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
}
kgem_bo_destroy(kgem, src_bo);

View File

@ -56,9 +56,24 @@ to_present_event(uintptr_t data)
#define MARK_PRESENT(x) ((void *)((uintptr_t)(x) | 2))
static int pipe_from_crtc(RRCrtcPtr crtc)
static inline xf86CrtcPtr unmask_crtc(xf86CrtcPtr crtc)
{
return crtc ? sna_crtc_to_pipe__safe(crtc->devPrivate) : -1;
return (xf86CrtcPtr)((uintptr_t)crtc & ~1);
}
static inline xf86CrtcPtr mark_crtc(xf86CrtcPtr crtc)
{
return (xf86CrtcPtr)((uintptr_t)crtc | 1);
}
static inline bool has_vblank(xf86CrtcPtr crtc)
{
return (uintptr_t)crtc & 1;
}
static inline int pipe_from_crtc(RRCrtcPtr crtc)
{
return crtc ? sna_crtc_pipe(crtc->devPrivate) : -1;
}
static uint32_t pipe_select(int pipe)
@ -98,7 +113,7 @@ static void vblank_complete(struct sna_present_event *info,
DBG(("%s: %d events complete\n", __FUNCTION__, info->n_event_id));
for (n = 0; n < info->n_event_id; n++) {
DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete%s\n", __FUNCTION__,
sna_crtc_to_pipe(info->crtc),
sna_crtc_pipe(unmask_crtc(info->crtc)),
(int)(ust / 1000000), (int)(ust % 1000000),
(long long)msc, (long long)info->target_msc,
(long long)info->event_id[n],
@ -142,7 +157,7 @@ static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
VG_CLEAR(vbl);
vbl.request.type = DRM_VBLANK_RELATIVE;
vbl.request.sequence = 0;
if (sna_wait_vblank(info->sna, &vbl, sna_crtc_to_pipe(info->crtc)) == 0) {
if (sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc)) == 0) {
ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec);
msc = sna_crtc_record_vblank(info->crtc, &vbl);
DBG(("%s: event=%lld, target msc=%lld, now %lld\n",
@ -155,7 +170,7 @@ static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
vbl.request.sequence = info->target_msc;
vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
if (sna_wait_vblank(info->sna, &vbl, sna_crtc_to_pipe(info->crtc)) == 0) {
if (sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc)) == 0) {
DBG(("%s: scheduled new vblank event for %lld\n", __FUNCTION__, (long long)info->target_msc));
free(timer);
return 0;
@ -173,7 +188,7 @@ static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
DBG(("%s: blocking wait!\n", __FUNCTION__));
vbl.request.type = DRM_VBLANK_ABSOLUTE;
vbl.request.sequence = info->target_msc;
(void)sna_wait_vblank(info->sna, &vbl, sna_crtc_to_pipe(info->crtc));
(void)sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc));
}
} else {
const struct ust_msc *swap = sna_crtc_last_swap(info->crtc);
@ -241,24 +256,31 @@ static int
sna_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
{
struct sna *sna = to_sna_from_screen(crtc->pScreen);
int pipe = pipe_from_crtc(crtc);
union drm_wait_vblank vbl;
DBG(("%s(pipe=%d)\n", __FUNCTION__, pipe));
DBG(("%s(pipe=%d)\n", __FUNCTION__, sna_crtc_pipe(crtc->devPrivate)));
if (sna_crtc_has_vblank(crtc->devPrivate)) {
DBG(("%s: vblank active, reusing last swap msc/ust\n",
__FUNCTION__));
goto last;
}
VG_CLEAR(vbl);
vbl.request.type = DRM_VBLANK_RELATIVE;
vbl.request.sequence = 0;
if (sna_wait_vblank(sna, &vbl, pipe) == 0) {
if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(crtc->devPrivate)) == 0) {
*ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec);
*msc = sna_crtc_record_vblank(crtc->devPrivate, &vbl);
} else {
const struct ust_msc *swap = sna_crtc_last_swap(crtc->devPrivate);
const struct ust_msc *swap;
last:
swap = sna_crtc_last_swap(crtc->devPrivate);
*ust = swap_ust(swap);
*msc = swap->msc;
}
DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld\n", __FUNCTION__, pipe,
DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld\n", __FUNCTION__,
sna_crtc_pipe(crtc->devPrivate),
(int)(*ust / 1000000), (int)(*ust % 1000000),
(long long)*msc));
@ -269,10 +291,13 @@ void
sna_present_vblank_handler(struct drm_event_vblank *event)
{
struct sna_present_event *info = to_present_event(event->user_data);
xf86CrtcPtr crtc = info->crtc;
vblank_complete(info,
ust64(event->tv_sec, event->tv_usec),
sna_crtc_record_event(info->crtc, event));
sna_crtc_record_event(unmask_crtc(crtc), event));
if (has_vblank(crtc))
sna_crtc_clear_vblank(unmask_crtc(crtc));
}
static int
@ -284,14 +309,14 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
union drm_wait_vblank vbl;
DBG(("%s(pipe=%d, event=%lld, msc=%lld)\n",
__FUNCTION__, pipe_from_crtc(crtc),
__FUNCTION__, sna_crtc_pipe(crtc->devPrivate),
(long long)event_id, (long long)msc));
swap = sna_crtc_last_swap(crtc->devPrivate);
assert((int64_t)(msc - swap->msc) >= 0);
if ((int64_t)(msc - swap->msc) <= 0) {
DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
pipe_from_crtc(crtc),
sna_crtc_pipe(crtc->devPrivate),
swap->tv_sec, swap->tv_usec,
(long long)swap->msc, (long long)msc,
(long long)event_id));
@ -300,13 +325,14 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
}
list_for_each_entry(tmp, &sna->present.vblank_queue, link) {
if (tmp->target_msc == msc && tmp->crtc == crtc->devPrivate) {
if (tmp->target_msc == msc &&
unmask_crtc(tmp->crtc) == crtc->devPrivate) {
uint64_t *events = tmp->event_id;
if (is_power_of_two(tmp->n_event_id)) {
events = malloc(2*sizeof(uint64_t)*tmp->n_event_id);
if (events == NULL)
goto fail;
return BadAlloc;
memcpy(events,
tmp->event_id,
@ -321,11 +347,13 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
events[tmp->n_event_id++] = event_id;
return Success;
}
if ((int64_t)(tmp->target_msc - msc) > 0)
if ((int64_t)(tmp->target_msc - msc) > 0) {
DBG(("%s: previous target_msc=%lld invalid for coalescing\n",
__FUNCTION__, (long long)tmp->target_msc));
break;
}
}
fail:
info = malloc(sizeof(struct sna_present_event) + sizeof(uint64_t));
if (info == NULL)
return BadAlloc;
@ -342,13 +370,18 @@ fail:
vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
vbl.request.sequence = msc;
vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(info->crtc))) {
if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(info->crtc))) {
DBG(("%s: vblank enqueue failed\n", __FUNCTION__));
if (!sna_fake_vblank(info)) {
list_del(&info->link);
free(info);
return BadAlloc;
}
} else {
if (msc - swap->msc == 1) {
sna_crtc_set_vblank(info->crtc);
info->crtc = mark_crtc(info->crtc);
}
}
return Success;
@ -444,6 +477,24 @@ sna_present_check_flip(RRCrtcPtr crtc,
return FALSE;
}
if (flip->pinned) {
assert(flip->gpu_bo);
if (sna->flags & SNA_LINEAR_FB) {
if (flip->gpu_bo->tiling != I915_TILING_NONE) {
DBG(("%s: pined bo, tilng=%d needs NONE\n",
__FUNCTION__, flip->gpu_bo->tiling));
return FALSE;
}
} else {
if (!sna->kgem.can_scanout_y &&
flip->gpu_bo->tiling == I915_TILING_Y) {
DBG(("%s: pined bo, tilng=%d and can't scanout Y\n",
__FUNCTION__, flip->gpu_bo->tiling));
return FALSE;
}
}
}
return TRUE;
}
@ -492,12 +543,14 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
swap = *sna_crtc_last_swap(info->crtc);
DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld (target %lld), event=%lld complete%s\n", __FUNCTION__,
info->crtc ? sna_crtc_to_pipe(info->crtc) : -1,
info->crtc ? sna_crtc_pipe(info->crtc) : -1,
swap.tv_sec, swap.tv_usec, (long long)swap.msc,
(long long)info->target_msc,
(long long)info->event_id[0],
info->target_msc && info->target_msc == swap.msc ? "" : ": MISS"));
present_event_notify(info->event_id[0], swap_ust(&swap), swap.msc);
if (info->crtc)
sna_crtc_clear_vblank(info->crtc);
if (info->sna->present.unflip) {
DBG(("%s: executing queued unflip (event=%lld)\n", __FUNCTION__, (long long)info->sna->present.unflip));
@ -540,6 +593,8 @@ flip(struct sna *sna,
return FALSE;
}
if (info->crtc)
sna_crtc_set_vblank(info->crtc);
return TRUE;
}
@ -560,7 +615,7 @@ get_flip_bo(PixmapPtr pixmap)
if (priv->gpu_bo->scanout)
return priv->gpu_bo;
if (sna->kgem.has_llc && !wedged(sna)) {
if (sna->kgem.has_llc && !wedged(sna) && !priv->pinned) {
struct kgem_bo *bo;
uint32_t tiling;

View File

@ -54,7 +54,7 @@ sna_format_for_depth(int depth)
{
switch (depth) {
case 1: return PICT_a1;
case 4: return PICT_a4;
case 4: return PICT_x4a4;
case 8: return PICT_a8;
case 15: return PICT_x1r5g5b5;
case 16: return PICT_r5g6b5;
@ -271,18 +271,6 @@ no_render_context_switch(struct kgem *kgem,
(void)new_mode;
}
static void
no_render_retire(struct kgem *kgem)
{
(void)kgem;
}
static void
no_render_expire(struct kgem *kgem)
{
(void)kgem;
}
static void
no_render_fini(struct sna *sna)
{
@ -316,8 +304,6 @@ const char *no_render_init(struct sna *sna)
render->fini = no_render_fini;
sna->kgem.context_switch = no_render_context_switch;
sna->kgem.retire = no_render_retire;
sna->kgem.expire = no_render_expire;
if (sna->kgem.has_blt)
sna->kgem.ring = KGEM_BLT;

View File

@ -238,8 +238,9 @@ struct sna_render {
int16_t w, int16_t h,
unsigned flags,
struct sna_composite_op *tmp);
#define COMPOSITE_PARTIAL 0x1
#define COMPOSITE_FALLBACK 0x80000000
#define COMPOSITE_PARTIAL 0x1
#define COMPOSITE_UPLOAD 0x40000000
#define COMPOSITE_FALLBACK 0x80000000
bool (*check_composite_spans)(struct sna *sna, uint8_t op,
PicturePtr dst, PicturePtr src,
@ -540,7 +541,7 @@ enum {
struct gen8_render_state {
unsigned gt;
const struct gt_info *info;
struct kgem_bo *general_bo;
uint32_t vs_state;

View File

@ -592,6 +592,8 @@ lerp32_opacity(PixmapPtr scratch,
uint32_t *ptr;
int stride, i;
sigtrap_assert_active();
ptr = (uint32_t*)((uint8_t *)scratch->devPrivate.ptr + scratch->devKind * y);
ptr += x;
stride = scratch->devKind / 4;

View File

@ -1707,8 +1707,7 @@ static void span_thread_add_box(struct sna *sna, void *data,
{
struct span_thread_boxes *b = data;
__DBG(("%s: adding %d boxes with alpha=%f\n",
__FUNCTION__, count, alpha));
__DBG(("%s: adding box with alpha=%f\n", __FUNCTION__, alpha));
if (unlikely(b->num_boxes == SPAN_THREAD_MAX_BOXES)) {
DBG(("%s: flushing %d boxes\n", __FUNCTION__, b->num_boxes));
@ -2370,6 +2369,7 @@ tor_blt_lerp32(struct sna *sna,
if (coverage == 0)
return;
sigtrap_assert_active();
ptr += box->y1 * stride + box->x1;
h = box->y2 - box->y1;

View File

@ -79,7 +79,7 @@ struct mono {
struct mono_polygon polygon;
};
#define I(x) pixman_fixed_to_int ((x) + pixman_fixed_1_minus_e/2)
#define I(x) pixman_fixed_to_int((x) + pixman_fixed_1_minus_e/2)
static struct quorem
floored_muldivrem(int32_t x, int32_t a, int32_t b)
@ -250,22 +250,22 @@ mono_add_line(struct mono *mono,
e->dxdy = floored_muldivrem(dx, pixman_fixed_1, dy);
e->x = floored_muldivrem((ytop - dst_y) * pixman_fixed_1 + pixman_fixed_1_minus_e/2 - p1->y,
e->x = floored_muldivrem((ytop - dst_y) * pixman_fixed_1 + pixman_fixed_1/2 - p1->y,
dx, dy);
e->x.quo += p1->x;
e->x.rem -= dy;
e->dy = dy;
__DBG(("%s: initial x=%d [%d.%d/%d] + dxdy=%d.%d/%d\n",
__FUNCTION__,
I(e->x.quo), e->x.quo, e->x.rem, e->dy,
e->dxdy.quo, e->dxdy.rem, e->dy));
}
e->x.quo += dst_x*pixman_fixed_1;
__DBG(("%s: initial x=%d [%d.%d/%d] + dxdy=%d.%d/%d\n",
__FUNCTION__,
I(e->x.quo), e->x.quo, e->x.rem, e->dy,
e->dxdy.quo, e->dxdy.rem, e->dy));
{
struct mono_edge **ptail = &polygon->y_buckets[ytop - mono->clip.extents.y1];
assert(ytop - mono->clip.extents.y1 < mono->clip.extents.y2 - mono->clip.extents.y1);
if (*ptail)
(*ptail)->prev = e;
e->next = *ptail;
@ -369,6 +369,10 @@ static struct mono_edge *mono_filter(struct mono_edge *edges)
e->x.rem == n->x.rem &&
e->dxdy.quo == n->dxdy.quo &&
e->dxdy.rem == n->dxdy.rem) {
assert(e->dy == n->dy);
__DBG(("%s: discarding cancellation pair (%d.%d) + (%d.%d)\n",
__FUNCTION__, e->x.quo, e->x.rem, e->dxdy.quo, e->dxdy.rem));
if (e->prev)
e->prev->next = n->next;
else
@ -379,8 +383,11 @@ static struct mono_edge *mono_filter(struct mono_edge *edges)
break;
e = n->next;
} else
} else {
__DBG(("%s: adding edge (%d.%d) + (%d.%d)/%d, height=%d\n",
__FUNCTION__, n->x.quo, n->x.rem, n->dxdy.quo, n->dxdy.rem, n->dy, n->height_left));
e = n;
}
}
return edges;
@ -571,6 +578,8 @@ mono_row(struct mono *c, int16_t y, int16_t h)
int winding = 0;
BoxRec box;
__DBG(("%s: y=%d, h=%d\n", __FUNCTION__, y, h));
DBG_MONO_EDGES(edge);
VALIDATE_MONO_EDGES(&c->head);
@ -581,6 +590,8 @@ mono_row(struct mono *c, int16_t y, int16_t h)
struct mono_edge *next = edge->next;
int16_t xend = I(edge->x.quo);
__DBG(("%s: adding edge dir=%d [winding=%d], x=%d [%d]\n",
__FUNCTION__, edge->dir, winding + edge->dir, xend, edge->x.quo));
if (--edge->height_left) {
if (edge->dy) {
edge->x.quo += edge->dxdy.quo;
@ -589,6 +600,8 @@ mono_row(struct mono *c, int16_t y, int16_t h)
++edge->x.quo;
edge->x.rem -= edge->dy;
}
__DBG(("%s: stepped edge (%d.%d) + (%d.%d)/%d, height=%d, prev_x=%d\n",
__FUNCTION__, edge->x.quo, edge->x.rem, edge->dxdy.quo, edge->dxdy.rem, edge->dy, edge->height_left, edge->x.quo));
}
if (edge->x.quo < prev_x) {
@ -612,17 +625,22 @@ mono_row(struct mono *c, int16_t y, int16_t h)
winding += edge->dir;
if (winding == 0) {
assert(I(next->x.quo) >= xend);
if (I(next->x.quo) > xend + 1) {
if (I(next->x.quo) > xend) {
__DBG(("%s: end span: %d\n", __FUNCTION__, xend));
if (xstart < c->clip.extents.x1)
xstart = c->clip.extents.x1;
if (xend > c->clip.extents.x2)
xend = c->clip.extents.x2;
if (xend > xstart)
if (xend > xstart) {
__DBG(("%s: emit span [%d, %d]\n", __FUNCTION__, xstart, xend));
c->span(c, xstart, xend, &box);
}
xstart = INT16_MIN;
}
} else if (xstart == INT16_MIN)
} else if (xstart == INT16_MIN) {
__DBG(("%s: starting new span: %d\n", __FUNCTION__, xend));
xstart = xend;
}
edge = next;
}
@ -684,9 +702,14 @@ mono_render(struct mono *mono)
for (i = 0; i < h; i = j) {
j = i + 1;
__DBG(("%s: row=%d, new edges? %d\n", __FUNCTION__,
i, polygon->y_buckets[i] != NULL));
if (polygon->y_buckets[i])
mono_merge_edges(mono, polygon->y_buckets[i]);
__DBG(("%s: row=%d, vertical? %d\n", __FUNCTION__,
i, mono->is_vertical));
if (mono->is_vertical) {
struct mono_edge *e = mono->head.next;
int min_height = h - i;
@ -701,6 +724,7 @@ mono_render(struct mono *mono)
j++;
if (j != i + 1)
mono_step_edges(mono, j - (i + 1));
__DBG(("%s: %d vertical rows\n", __FUNCTION__, j-i));
}
mono_row(mono, i, j-i);
@ -1013,6 +1037,7 @@ mono_inplace_fill_box(struct sna *sna,
box->x2 - box->x1,
box->y2 - box->y1,
fill->color));
sigtrap_assert_active();
pixman_fill(fill->data, fill->stride, fill->bpp,
box->x1, box->y1,
box->x2 - box->x1,
@ -1034,6 +1059,7 @@ mono_inplace_fill_boxes(struct sna *sna,
box->x2 - box->x1,
box->y2 - box->y1,
fill->color));
sigtrap_assert_active();
pixman_fill(fill->data, fill->stride, fill->bpp,
box->x1, box->y1,
box->x2 - box->x1,
@ -1421,10 +1447,13 @@ mono_triangles_span_converter(struct sna *sna,
mono_render(&mono);
mono.op.done(mono.sna, &mono.op);
}
mono_fini(&mono);
if (!was_clear && !operator_is_bounded(op)) {
xPointFixed p1, p2;
DBG(("%s: performing unbounded clear\n", __FUNCTION__));
if (!mono_init(&mono, 2+3*count))
return false;
@ -1470,7 +1499,6 @@ mono_triangles_span_converter(struct sna *sna,
mono_fini(&mono);
}
mono_fini(&mono);
REGION_UNINIT(NULL, &mono.clip);
return true;
}

View File

@ -1655,8 +1655,7 @@ static void span_thread_add_box(struct sna *sna, void *data,
{
struct span_thread_boxes *b = data;
__DBG(("%s: adding %d boxes with alpha=%f\n",
__FUNCTION__, count, alpha));
__DBG(("%s: adding box with alpha=%f\n", __FUNCTION__, alpha));
if (unlikely(b->num_boxes == SPAN_THREAD_MAX_BOXES)) {
DBG(("%s: flushing %d boxes\n", __FUNCTION__, b->num_boxes));
@ -2386,6 +2385,7 @@ tor_blt_lerp32(struct sna *sna,
if (coverage == 0)
return;
sigtrap_assert_active();
ptr += box->y1 * stride + box->x1;
h = box->y2 - box->y1;

View File

@ -81,14 +81,11 @@ static int sna_video_sprite_stop(ddStopVideo_ARGS)
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(video->sna->scrn);
int i;
for (i = 0; i < config->num_crtc; i++) {
for (i = 0; i < video->sna->mode.num_real_crtc; i++) {
xf86CrtcPtr crtc = config->crtc[i];
int pipe;
if (sna_crtc_id(crtc) == 0)
break;
pipe = sna_crtc_to_pipe(crtc);
pipe = sna_crtc_pipe(crtc);
if (video->bo[pipe] == NULL)
continue;
@ -221,7 +218,7 @@ sna_video_sprite_show(struct sna *sna,
BoxPtr dstBox)
{
struct local_mode_set_plane s;
int pipe = sna_crtc_to_pipe(crtc);
int pipe = sna_crtc_pipe(crtc);
/* XXX handle video spanning multiple CRTC */
@ -402,7 +399,7 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS)
goto err;
}
for (i = 0; i < config->num_crtc; i++) {
for (i = 0; i < video->sna->mode.num_real_crtc; i++) {
xf86CrtcPtr crtc = config->crtc[i];
struct sna_video_frame frame;
int pipe;
@ -411,10 +408,7 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS)
RegionRec reg;
Rotation rotation;
if (sna_crtc_id(crtc) == 0)
break;
pipe = sna_crtc_to_pipe(crtc);
pipe = sna_crtc_pipe(crtc);
sna_video_frame_init(video, format->id, width, height, &frame);
@ -611,7 +605,7 @@ static bool sna_video_has_sprites(struct sna *sna)
for (i = 0; i < sna->mode.num_real_crtc; i++) {
if (!sna_crtc_to_sprite(config->crtc[i])) {
DBG(("%s: no sprite found on pipe %d\n", __FUNCTION__, sna_crtc_to_pipe(config->crtc[i])));
DBG(("%s: no sprite found on pipe %d\n", __FUNCTION__, sna_crtc_pipe(config->crtc[i])));
return false;
}
}

View File

@ -94,8 +94,6 @@ struct intel_mode {
intel_pageflip_abort_proc abort;
void *data;
} pageflip;
Bool delete_dp_12_displays;
};
struct intel_pageflip {
@ -2248,10 +2246,6 @@ Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
intel->use_pageflipping = TRUE;
}
if (xf86ReturnOptValBool(intel->Options, OPTION_DELETE_DP12, FALSE)) {
mode->delete_dp_12_displays = TRUE;
}
intel->modes = mode;
drmModeFreeResources(mode_res);
return TRUE;
@ -2515,12 +2509,11 @@ intel_mode_hotplug(struct intel_screen_private *intel)
int i, j;
Bool found;
Bool changed = FALSE;
struct intel_mode *mode = intel->modes;
mode_res = drmModeGetResources(intel->drmSubFD);
if (!mode_res)
goto out;
restart_destroy:
for (i = 0; i < config->num_output; i++) {
xf86OutputPtr output = config->output[i];
struct intel_output *intel_output;
@ -2542,11 +2535,6 @@ restart_destroy:
RROutputChanged(output->randr_output, TRUE);
changed = TRUE;
if (mode->delete_dp_12_displays) {
RROutputDestroy(output->randr_output);
xf86OutputDestroy(output);
goto restart_destroy;
}
}
/* find new output ids we don't have outputs for */

View File

@ -766,7 +766,7 @@ I830HandleUEvents(int fd, void *closure)
udev_device_unref(dev);
}
static bool has_randr(void)
static int has_randr(void)
{
#if HAS_DIXREGISTERPRIVATEKEY
return dixPrivateKeyRegistered(rrPrivKey);

2
test/.gitignore vendored
View File

@ -11,6 +11,7 @@ cursor-test
render-fill
render-trapezoid
render-trapezoid-image
render-triangle
render-fill-copy
render-composite-solid
render-composite-solid-mask
@ -18,6 +19,7 @@ render-copyarea
render-copyarea-mask
render-copyarea-size
render-copy-alphaless
render-glyphs
mixed-stress
lowlevel-blt-bench
vsync.avi

View File

@ -12,8 +12,10 @@ stress_TESTS = \
DrawSegments \
cursor-test \
render-fill \
render-glyphs \
render-trapezoid \
render-trapezoid-image \
render-triangle \
render-fill-copy \
render-composite-solid \
render-composite-solid-mask \

View File

@ -29,6 +29,7 @@
#include <xcb/dri3.h>
#include <xcb/sync.h>
#include <unistd.h>
#include <stdlib.h>
#include "dri3.h"
@ -109,12 +110,45 @@ void dri3_fence_free(Display *dpy, struct dri3_fence *fence)
xcb_sync_destroy_fence(c, fence->xid);
}
static void dri3_query_version(xcb_connection_t *c, int *major, int *minor)
{
xcb_dri3_query_version_reply_t *reply;
reply = xcb_dri3_query_version_reply(c,
xcb_dri3_query_version(c,
XCB_DRI3_MAJOR_VERSION,
XCB_DRI3_MINOR_VERSION),
NULL);
if (reply != NULL) {
*major = reply->major_version;
*minor = reply->minor_version;
free(reply);
}
}
static int dri3_exists(xcb_connection_t *c)
{
const xcb_query_extension_reply_t *ext;
int major, minor;
major = minor = -1;
ext = xcb_get_extension_data(c, &xcb_dri3_id);
if (ext != NULL && ext->present)
dri3_query_version(c, &major, &minor);
return major >= 0;
}
int dri3_open__full(Display *dpy, Window root, unsigned provider)
{
xcb_connection_t *c = XGetXCBConnection(dpy);
xcb_dri3_open_cookie_t cookie;
xcb_dri3_open_reply_t *reply;
if (!dri3_exists(c))
return -1;
cookie = xcb_dri3_open(c, root, provider);
reply = xcb_dri3_open_reply(c, cookie, NULL);

View File

@ -249,7 +249,6 @@ static void run(Display *dpy, Window win, const char *name, unsigned options)
free(ev);
} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, Q)));
}
assert(p);
b->busy = (options & NOCOPY) == 0;
if (b->fence.xid) {

View File

@ -1564,6 +1564,7 @@ static int test_dri3_tiling(Display *dpy)
unsigned int width, height;
unsigned border, depth, bpp;
unsigned stride, size;
void *Q;
int x, y;
int device;
int line = -1;
@ -1594,8 +1595,10 @@ static int test_dri3_tiling(Display *dpy)
width, height, stride, size);
_x_error_occurred = 0;
Q = setup_msc(dpy, root);
for (t = 0; t < sizeof(tiling)/sizeof(tiling[0]); t++) {
uint64_t msc;
uint32_t src;
int src_fd;
Pixmap src_pix;
@ -1618,6 +1621,8 @@ static int test_dri3_tiling(Display *dpy)
width, height, depth,
src_fd, bpp, stride, size);
msc = wait_vblank(dpy, root, Q);
xcb_present_pixmap(XGetXCBConnection(dpy),
win, src_pix,
0, /* sbc */
@ -1629,10 +1634,27 @@ static int test_dri3_tiling(Display *dpy)
None, /* wait fence */
None,
XCB_PRESENT_OPTION_NONE,
0, /* target msc */
0, /* divisor */
msc + 2, /* target msc */
1, /* divisor */
0, /* remainder */
0, NULL);
xcb_present_pixmap(XGetXCBConnection(dpy),
win, src_pix,
0, /* sbc */
0, /* valid */
0, /* update */
0, /* x_off */
0, /* y_off */
None,
None, /* wait fence */
None,
XCB_PRESENT_OPTION_NONE,
msc + 3, /* target msc */
1, /* divisor */
0, /* remainder */
0, NULL);
XSync(dpy, True);
if (_x_error_occurred) {
line = __LINE__;
@ -1645,10 +1667,12 @@ static int test_dri3_tiling(Display *dpy)
gem_close(device, src);
}
teardown_msc(dpy, Q);
return 0;
fail:
printf("%s failed with tiling %d, line %d\n", __func__, tiling[t], line);
teardown_msc(dpy, Q);
return 1;
}

441
test/render-glyphs.c Normal file
View File

@ -0,0 +1,441 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdarg.h>
#include <string.h>
#include <X11/Xutil.h> /* for XDestroyImage */
#include <pixman.h> /* for pixman blt functions */
#include "test.h"
static const XRenderColor colors[] = {
/* red, green, blue, alpha */
{ 0 },
{ 0, 0, 0, 0xffff },
{ 0xffff, 0, 0, 0xffff },
{ 0, 0xffff, 0, 0xffff },
{ 0, 0, 0xffff, 0xffff },
{ 0xffff, 0xffff, 0xffff, 0xffff },
};
static struct clip {
void *func;
} clips[] = {
{ NULL },
};
static int _x_error_occurred;
static int
_check_error_handler(Display *display,
XErrorEvent *event)
{
_x_error_occurred = 1;
return False; /* ignored */
}
static void clear(struct test_display *dpy,
struct test_target *tt,
const XRenderColor *c)
{
XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, c,
0, 0, tt->width, tt->height);
}
static bool check_op(struct test_display *dpy, int op, struct test_target *tt)
{
XRenderColor render_color = {0};
XSync(dpy->dpy, True);
_x_error_occurred = 0;
XRenderFillRectangle(dpy->dpy, op,
tt->picture, &render_color,
0, 0, 0, 0);
XSync(dpy->dpy, True);
return _x_error_occurred == 0;
}
struct glyph_iter {
enum {
GLYPHS, OP, DST, SRC, MASK, CLIP,
} stage;
int glyph_format;
int op;
int dst_color;
int src_color;
int mask_format;
int clip;
struct {
struct test_display *dpy;
struct test_target tt;
GlyphSet glyphset;
Picture src;
XRenderPictFormat *mask_format;
} ref, out;
};
static void glyph_iter_init(struct glyph_iter *gi,
struct test *t, enum target target)
{
memset(gi, 0, sizeof(*gi));
gi->out.dpy = &t->out;
test_target_create_render(&t->out, target, &gi->out.tt);
gi->ref.dpy = &t->ref;
test_target_create_render(&t->ref, target, &gi->ref.tt);
gi->stage = GLYPHS;
gi->glyph_format = -1;
gi->op = -1;
gi->dst_color = -1;
gi->src_color = -1;
gi->mask_format = -1;
gi->clip = -1;
}
static void render_clear(char *image, int image_size, int bpp)
{
memset(image, 0, image_size);
}
static void render_black(char *image, int image_size, int bpp)
{
if (bpp == 4) {
uint32_t *p = (uint32_t *)image;
image_size /= 4;
while (image_size--)
*p++ = 0x000000ff;
} else
memset(image, 0x55, image_size);
}
static void render_green(char *image, int image_size, int bpp)
{
if (bpp == 4) {
uint32_t *p = (uint32_t *)image;
image_size /= 4;
while (image_size--)
*p++ = 0xffff0000;
} else
memset(image, 0xaa, image_size);
}
static void render_white(char *image, int image_size, int bpp)
{
memset(image, 0xff, image_size);
}
static GlyphSet create_glyphs(Display *dpy, int format_id)
{
#define N_GLYPHS 4
XRenderPictFormat *format;
XGlyphInfo glyph = { 8, 8, 0, 0, 8, 0 };
char image[4*8*8];
GlyphSet glyphset;
Glyph gid;
int image_size;
int bpp;
int n;
format = XRenderFindStandardFormat(dpy, format_id);
if (format == NULL)
return 0;
switch (format_id) {
case PictStandardARGB32:
case PictStandardRGB24:
image_size = 4 * 8 * 8;
bpp = 4;
break;
case PictStandardA8:
case PictStandardA4:
image_size = 8 * 8;
bpp = 1;
break;
case PictStandardA1:
image_size = 8;
bpp = 0;
break;
default:
return 0;
}
glyphset = XRenderCreateGlyphSet(dpy, format);
for (n = 0; n < N_GLYPHS; n++) {
gid = n;
switch (n) {
case 0: render_clear(image, image_size, bpp); break;
case 1: render_black(image, image_size, bpp); break;
case 2: render_green(image, image_size, bpp); break;
case 3: render_white(image, image_size, bpp); break;
}
XRenderAddGlyphs(dpy, glyphset,
&gid, &glyph, 1, image, image_size);
}
return glyphset;
}
static const char *glyph_name(int n)
{
switch (n) {
case 0: return "clear";
case 1: return "black";
case 2: return "green";
case 3: return "white";
default: return "unknown";
}
}
static bool glyph_iter_next(struct glyph_iter *gi)
{
restart:
if (gi->stage == GLYPHS) {
if (++gi->glyph_format == PictStandardNUM)
return false;
if (gi->out.glyphset)
XRenderFreeGlyphSet(gi->out.dpy->dpy,
gi->out.glyphset);
gi->out.glyphset = create_glyphs(gi->out.dpy->dpy,
gi->glyph_format);
if (gi->ref.glyphset)
XRenderFreeGlyphSet(gi->ref.dpy->dpy,
gi->ref.glyphset);
gi->ref.glyphset = create_glyphs(gi->ref.dpy->dpy,
gi->glyph_format);
gi->stage++;
}
if (gi->stage == OP) {
do {
if (++gi->op == 255)
goto reset_op;
} while (!check_op(gi->out.dpy, gi->op, &gi->out.tt) ||
!check_op(gi->ref.dpy, gi->op, &gi->ref.tt));
gi->stage++;
}
if (gi->stage == DST) {
if (++gi->dst_color == ARRAY_SIZE(colors))
goto reset_dst;
gi->stage++;
}
if (gi->stage == SRC) {
if (++gi->src_color == ARRAY_SIZE(colors))
goto reset_src;
if (gi->ref.src)
XRenderFreePicture(gi->ref.dpy->dpy, gi->ref.src);
gi->ref.src = XRenderCreateSolidFill(gi->ref.dpy->dpy,
&colors[gi->src_color]);
if (gi->out.src)
XRenderFreePicture(gi->out.dpy->dpy, gi->out.src);
gi->out.src = XRenderCreateSolidFill(gi->out.dpy->dpy,
&colors[gi->src_color]);
gi->stage++;
}
if (gi->stage == MASK) {
if (++gi->mask_format > PictStandardNUM)
goto reset_mask;
if (gi->mask_format == PictStandardRGB24)
gi->mask_format++;
if (gi->mask_format < PictStandardNUM) {
gi->out.mask_format = XRenderFindStandardFormat(gi->out.dpy->dpy,
gi->mask_format);
gi->ref.mask_format = XRenderFindStandardFormat(gi->ref.dpy->dpy,
gi->mask_format);
} else {
gi->out.mask_format = NULL;
gi->ref.mask_format = NULL;
}
gi->stage++;
}
if (gi->stage == CLIP) {
if (++gi->clip == ARRAY_SIZE(clips))
goto reset_clip;
gi->stage++;
}
gi->stage--;
return true;
reset_op:
gi->op = -1;
reset_dst:
gi->dst_color = -1;
reset_src:
gi->src_color = -1;
reset_mask:
gi->mask_format = -1;
reset_clip:
gi->clip = -1;
gi->stage--;
goto restart;
}
static void glyph_iter_fini(struct glyph_iter *gi)
{
if (gi->out.glyphset)
XRenderFreeGlyphSet (gi->out.dpy->dpy, gi->out.glyphset);
if (gi->ref.glyphset)
XRenderFreeGlyphSet (gi->ref.dpy->dpy, gi->ref.glyphset);
test_target_destroy_render(gi->out.dpy, &gi->out.tt);
test_target_destroy_render(gi->ref.dpy, &gi->ref.tt);
}
static const char *stdformat_to_str(int id)
{
switch (id) {
case PictStandardARGB32: return "ARGB32";
case PictStandardRGB24: return "RGB24";
case PictStandardA8: return "A8";
case PictStandardA4: return "A4";
case PictStandardA1: return "A1";
default: return "none";
}
}
static char *glyph_iter_to_string(struct glyph_iter *gi,
const char *format,
...)
{
static char buf[100];
va_list ap;
int len;
len = sprintf(buf, "glyphs=%s, op=%d, dst=%08x, src=%08x, mask=%s",
stdformat_to_str(gi->glyph_format), gi->op,
xrender_color(&colors[gi->dst_color]),
xrender_color(&colors[gi->src_color]),
stdformat_to_str(gi->mask_format));
if (format) {
buf[len++] = ' ';
va_start(ap, format);
vsprintf(buf+len, format, ap);
va_end(ap);
}
return buf;
}
static void single(struct test *t, enum target target)
{
struct glyph_iter gi;
int n;
printf("Testing single glyph (%s): ", test_target_name(target));
fflush(stdout);
glyph_iter_init(&gi, t, target);
while (glyph_iter_next(&gi)) {
XGlyphElt8 elt;
char id[N_GLYPHS];
for (n = 0; n < N_GLYPHS; n++) {
id[n] = n;
elt.chars = &id[n];
elt.nchars = 1;
elt.xOff = 0;
elt.yOff = 0;
clear(gi.out.dpy, &gi.out.tt, &colors[gi.dst_color]);
elt.glyphset = gi.out.glyphset;
XRenderCompositeText8 (gi.out.dpy->dpy, gi.op,
gi.out.src,
gi.out.tt.picture,
gi.out.mask_format,
0, 0,
0, 8,
&elt, 1);
clear(gi.ref.dpy, &gi.ref.tt, &colors[gi.dst_color]);
elt.glyphset = gi.ref.glyphset;
XRenderCompositeText8 (gi.ref.dpy->dpy, gi.op,
gi.ref.src,
gi.ref.tt.picture,
gi.ref.mask_format,
0, 0,
0, 8,
&elt, 1);
test_compare(t,
gi.out.tt.draw, gi.out.tt.format,
gi.ref.tt.draw, gi.ref.tt.format,
0, 0, gi.out.tt.width, gi.out.tt.height,
glyph_iter_to_string(&gi,
"glyph=%s",
glyph_name(n)));
}
elt.chars = &id[0];
elt.nchars = n;
clear(gi.out.dpy, &gi.out.tt, &colors[gi.dst_color]);
elt.glyphset = gi.out.glyphset;
XRenderCompositeText8 (gi.out.dpy->dpy, gi.op,
gi.out.src,
gi.out.tt.picture,
gi.out.mask_format,
0, 0,
0, 8,
&elt, 1);
clear(gi.ref.dpy, &gi.ref.tt, &colors[gi.dst_color]);
elt.glyphset = gi.ref.glyphset;
XRenderCompositeText8 (gi.ref.dpy->dpy, gi.op,
gi.ref.src,
gi.ref.tt.picture,
gi.ref.mask_format,
0, 0,
0, 8,
&elt, 1);
test_compare(t,
gi.out.tt.draw, gi.out.tt.format,
gi.ref.tt.draw, gi.ref.tt.format,
0, 0, gi.out.tt.width, gi.out.tt.height,
glyph_iter_to_string(&gi, "all"));
}
glyph_iter_fini(&gi);
}
int main(int argc, char **argv)
{
struct test test;
int t;
test_init(&test, argc, argv);
XSetErrorHandler(_check_error_handler);
for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
single(&test, t);
//overlapping(&test, t);
//gap(&test, t);
//mixed(&test, t);
}
return 0;
}

View File

@ -403,16 +403,141 @@ static void trap_tests(struct test *t,
free(traps);
}
enum edge {
EDGE_SHARP = PolyEdgeSharp,
EDGE_SMOOTH,
};
static const char *edge_name(enum edge edge)
{
switch (edge) {
default:
case EDGE_SHARP: return "sharp";
case EDGE_SMOOTH: return "smooth";
}
}
static void set_edge(Display *dpy, Picture p, enum edge edge)
{
XRenderPictureAttributes a;
a.poly_edge = edge;
XRenderChangePicture(dpy, p, CPPolyEdge, &a);
}
static void edge_test(struct test *t,
enum mask mask,
enum edge edge,
enum target target)
{
struct test_target out, ref;
XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
Picture src_ref, src_out;
XTrapezoid trap;
int left_or_right, p;
test_target_create_render(&t->out, target, &out);
set_edge(t->out.dpy, out.picture, edge);
src_out = XRenderCreateSolidFill(t->out.dpy, &white);
test_target_create_render(&t->ref, target, &ref);
set_edge(t->ref.dpy, ref.picture, edge);
src_ref = XRenderCreateSolidFill(t->ref.dpy, &white);
printf("Testing edges (with mask %s and %s edges) (%s): ",
mask_name(mask),
edge_name(edge),
test_target_name(target));
fflush(stdout);
for (left_or_right = 0; left_or_right <= 1; left_or_right++) {
for (p = -64; p <= out.width + 64; p++) {
char buf[80];
if (left_or_right) {
trap.left.p1.x = 0;
trap.left.p1.y = 0;
trap.left.p2.x = 0;
trap.left.p2.y = out.height << 16;
trap.right.p1.x = p << 16;
trap.right.p1.y = 0;
trap.right.p2.x = out.width << 16;
trap.right.p2.y = out.height << 16;
} else {
trap.right.p1.x = out.width << 16;
trap.right.p1.y = 0;
trap.right.p2.x = out.width << 16;
trap.right.p2.y = out.height << 16;
trap.left.p1.x = 0;
trap.left.p1.y = 0;
trap.left.p2.x = p << 16;
trap.left.p2.y = out.height << 16;
}
trap.top = 0;
trap.bottom = out.height << 16;
sprintf(buf,
"trap=((%d, %d), (%d, %d)), ((%d, %d), (%d, %d))\n",
trap.left.p1.x >> 16, trap.left.p1.y >> 16,
trap.left.p2.x >> 16, trap.left.p2.y >> 16,
trap.right.p1.x >> 16, trap.right.p1.y >> 16,
trap.right.p2.x >> 16, trap.right.p2.y >> 16);
clear(&t->out, &out);
XRenderCompositeTrapezoids(t->out.dpy,
PictOpSrc,
src_out,
out.picture,
mask_format(t->out.dpy, mask),
0, 0,
&trap, 1);
clear(&t->ref, &ref);
XRenderCompositeTrapezoids(t->ref.dpy,
PictOpSrc,
src_ref,
ref.picture,
mask_format(t->ref.dpy, mask),
0, 0,
&trap, 1);
test_compare(t,
out.draw, out.format,
ref.draw, ref.format,
0, 0, out.width, out.height,
buf);
}
}
XRenderFreePicture(t->out.dpy, src_out);
test_target_destroy_render(&t->out, &out);
XRenderFreePicture(t->ref.dpy, src_ref);
test_target_destroy_render(&t->ref, &ref);
printf("pass\n");
}
int main(int argc, char **argv)
{
struct test test;
int i, dx, dy;
enum target target;
enum mask mask;
enum edge edge;
enum trapezoid trapezoid;
test_init(&test, argc, argv);
for (target = TARGET_FIRST; target <= TARGET_LAST; target++) {
for (mask = MASK_NONE; mask <= MASK_A8; mask++)
for (edge = EDGE_SHARP; edge <= EDGE_SMOOTH; edge++)
edge_test(&test, mask, edge, target);
}
for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
int reps = REPS(i), sets = SETS(i);

180
test/render-triangle.c Normal file
View File

@ -0,0 +1,180 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "test.h"
enum edge {
EDGE_SHARP = PolyEdgeSharp,
EDGE_SMOOTH,
};
static void set_edge(Display *dpy, Picture p, enum edge edge)
{
XRenderPictureAttributes a;
a.poly_edge = edge;
XRenderChangePicture(dpy, p, CPPolyEdge, &a);
}
static XRenderPictFormat *mask_format(Display *dpy, enum mask mask)
{
switch (mask) {
default:
case MASK_NONE: return NULL;
case MASK_A1: return XRenderFindStandardFormat(dpy, PictStandardA1);
case MASK_A8: return XRenderFindStandardFormat(dpy, PictStandardA8);
}
}
static const char *mask_name(enum mask mask)
{
switch (mask) {
default:
case MASK_NONE: return "none";
case MASK_A1: return "a1";
case MASK_A8: return "a8";
}
}
static const char *edge_name(enum edge edge)
{
switch (edge) {
default:
case EDGE_SHARP: return "sharp";
case EDGE_SMOOTH: return "smooth";
}
}
static void clear(struct test_display *dpy, struct test_target *tt)
{
XRenderColor render_color = {0};
XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color,
0, 0, tt->width, tt->height);
}
static void step_to_point(int step, int width, int height, XPointFixed *p)
{
do {
p->x = (step - 64) << 16;
p->y = -64 << 16;
step -= width - 128;
if (step <= 0)
return;
p->x = (width + 64) << 16;
p->y = (step - 64) << 16;
step -= height - 128;
if (step <= 0)
return;
p->x = (width + 64 - step) << 16;
p->y = (height + 64) << 16;
step -= width - 128;
if (step <= 0)
return;
p->x = -64 << 16;
p->y = (height + 64 - step) << 16;
step -= height - 128;
} while (step > 0);
}
static void edge_test(struct test *t,
enum mask mask,
enum edge edge,
enum target target)
{
struct test_target out, ref;
XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
Picture src_ref, src_out;
XTriangle tri;
unsigned step, max;
test_target_create_render(&t->out, target, &out);
set_edge(t->out.dpy, out.picture, edge);
src_out = XRenderCreateSolidFill(t->out.dpy, &white);
test_target_create_render(&t->ref, target, &ref);
set_edge(t->ref.dpy, ref.picture, edge);
src_ref = XRenderCreateSolidFill(t->ref.dpy, &white);
printf("Testing edges (with mask %s and %s edges) (%s): ",
mask_name(mask),
edge_name(edge),
test_target_name(target));
fflush(stdout);
max = 2*(out.width + 128 + out.height+128);
step = 0;
for (step = 0; step <= max; step++) {
char buf[80];
step_to_point(step, out.width, out.height, &tri.p1);
step_to_point(step + out.width + 128,
out.width, out.height,
&tri.p2);
step_to_point(step + out.height + 128 + 2*(out.width + 128),
out.width, out.height,
&tri.p3);
sprintf(buf,
"tri=((%d, %d), (%d, %d), (%d, %d))\n",
tri.p1.x >> 16, tri.p1.y >> 16,
tri.p2.x >> 16, tri.p2.y >> 16,
tri.p3.x >> 16, tri.p3.y >> 16);
clear(&t->out, &out);
XRenderCompositeTriangles(t->out.dpy,
PictOpSrc,
src_out,
out.picture,
mask_format(t->out.dpy, mask),
0, 0,
&tri, 1);
clear(&t->ref, &ref);
XRenderCompositeTriangles(t->ref.dpy,
PictOpSrc,
src_ref,
ref.picture,
mask_format(t->ref.dpy, mask),
0, 0,
&tri, 1);
test_compare(t,
out.draw, out.format,
ref.draw, ref.format,
0, 0, out.width, out.height,
buf);
}
XRenderFreePicture(t->out.dpy, src_out);
test_target_destroy_render(&t->out, &out);
XRenderFreePicture(t->ref.dpy, src_ref);
test_target_destroy_render(&t->ref, &ref);
printf("pass\n");
}
int main(int argc, char **argv)
{
struct test test;
enum target target;
enum mask mask;
enum edge edge;
test_init(&test, argc, argv);
for (target = TARGET_FIRST; target <= TARGET_LAST; target++) {
for (mask = MASK_NONE; mask <= MASK_A8; mask++)
for (edge = EDGE_SHARP; edge <= EDGE_SMOOTH; edge++)
edge_test(&test, mask, edge, target);
}
return 0;
}

View File

@ -107,6 +107,15 @@ static inline uint32_t color(uint8_t red, uint8_t green, uint8_t blue, uint8_t a
return alpha << 24 | ra >> 8 << 16 | ga >> 8 << 8 | ba >> 8;
}
static inline uint32_t xrender_color(const XRenderColor *c)
{
uint32_t ra = c->red * c->alpha;
uint32_t ga = c->green * c->alpha;
uint32_t ba = c->blue * c->alpha;
return c->alpha >> 8 << 24 | ra >> 24 << 16 | ga >> 24 << 8 | ba >> 24;
}
void test_timer_start(struct test_display *t, struct timespec *tv);
double test_timer_stop(struct test_display *t, struct timespec *tv);

View File

@ -197,13 +197,10 @@ void test_compare(struct test *t,
const char *info)
{
XImage out_image, ref_image;
Pixmap tmp;
char *out, *ref;
uint32_t *out, *ref;
char buf[600];
uint32_t mask;
int i, j;
XGCValues gcv;
GC gc;
if (w * h * 4 > t->out.max_shm_size)
return test_compare_fallback(t,
@ -214,37 +211,24 @@ void test_compare(struct test *t,
test_init_image(&out_image, &t->out.shm, out_format, w, h);
test_init_image(&ref_image, &t->ref.shm, ref_format, w, h);
gcv.graphics_exposures = 0;
die_unless(out_image.depth == ref_image.depth);
die_unless(out_image.bits_per_pixel == ref_image.bits_per_pixel);
die_unless(out_image.bits_per_pixel == 32);
mask = depth_mask(out_image.depth);
XShmGetImage(t->out.dpy, out_draw, &out_image, x, y, AllPlanes);
out = (uint32_t *)out_image.data;
tmp = XCreatePixmap(t->out.dpy, out_draw, w, h, out_image.depth);
gc = XCreateGC(t->out.dpy, tmp, GCGraphicsExposures, &gcv);
XCopyArea(t->out.dpy, out_draw, tmp, gc, x, y, w, h, 0, 0);
XShmGetImage(t->out.dpy, tmp, &out_image, 0, 0, AllPlanes);
XFreeGC(t->out.dpy, gc);
XFreePixmap(t->out.dpy, tmp);
out = out_image.data;
tmp = XCreatePixmap(t->ref.dpy, ref_draw, w, h, ref_image.depth);
gc = XCreateGC(t->ref.dpy, tmp, GCGraphicsExposures, &gcv);
XCopyArea(t->ref.dpy, ref_draw, tmp, gc, x, y, w, h, 0, 0);
XShmGetImage(t->ref.dpy, tmp, &ref_image, 0, 0, AllPlanes);
XFreeGC(t->ref.dpy, gc);
XFreePixmap(t->ref.dpy, tmp);
ref = ref_image.data;
XShmGetImage(t->ref.dpy, ref_draw, &ref_image, x, y, AllPlanes);
ref = (uint32_t *)ref_image.data;
/* Start with an exact comparison. However, one quicky desires
* a fuzzy comparator to hide hardware inaccuracies...
*/
mask = depth_mask(out_image.depth);
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
uint32_t a = ((uint32_t *)out)[i] & mask;
uint32_t b = ((uint32_t *)ref)[i] & mask;
uint32_t a = out[i] & mask;
uint32_t b = ref[i] & mask;
if (a != b && pixel_difference(a, b) > MAX_DELTA) {
show_pixels(buf,
&out_image, &ref_image,
@ -255,8 +239,8 @@ void test_compare(struct test *t,
x,i, y,j, a, b, pixel_difference(a, b), buf, info);
}
}
out += out_image.bytes_per_line;
ref += ref_image.bytes_per_line;
out = (uint32_t *)((char *)out + out_image.bytes_per_line);
ref = (uint32_t *)((char *)ref + ref_image.bytes_per_line);
}
}

View File

@ -20,6 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* To compile standalone: gcc -o dri3info dri3info.c `pkg-config --cflags --libs xcb-dri3 x11-xcb xrandr xxf86vm libdrm`
*/
#include <X11/Xlib.h>

View File

@ -111,7 +111,7 @@ struct display {
Cursor invisible_cursor;
Cursor visible_cursor;
XcursorImage cursor_image;
XcursorImage cursor_image; /* first only */
int cursor_serial;
int cursor_x;
int cursor_y;
@ -1614,14 +1614,17 @@ static Cursor display_load_invisible_cursor(struct display *display)
static Cursor display_get_visible_cursor(struct display *display)
{
if (display->cursor_serial != display->cursor_image.size) {
DBG(CURSOR, ("%s updating cursor\n", DisplayString(display->dpy)));
struct display *first = display->ctx->display;
if (display->cursor_serial != first->cursor_serial) {
DBG(CURSOR, ("%s updating cursor %dx%d, serial %d\n",
DisplayString(display->dpy), first->cursor_image.width, first->cursor_image.height, first->cursor_serial));
if (display->visible_cursor)
XFreeCursor(display->dpy, display->visible_cursor);
display->visible_cursor = XcursorImageLoadCursor(display->dpy, &display->cursor_image);
display->cursor_serial = display->cursor_image.size;
display->visible_cursor = XcursorImageLoadCursor(display->dpy, &first->cursor_image);
display->cursor_serial = first->cursor_serial;
}
return display->visible_cursor;
@ -1644,7 +1647,7 @@ static void display_load_visible_cursor(struct display *display, XFixesCursorIma
display->cursor_image.height = cur->height;
display->cursor_image.xhot = cur->xhot;
display->cursor_image.yhot = cur->yhot;
display->cursor_image.size++;
display->cursor_serial++;
n = cur->width*cur->height;
src = cur->pixels;
@ -1652,11 +1655,24 @@ static void display_load_visible_cursor(struct display *display, XFixesCursorIma
while (n--)
*dst++ = *src++;
DBG(CURSOR, ("%s marking cursor changed\n", DisplayString(display->dpy)));
display->cursor_moved++;
if (display->cursor != display->invisible_cursor) {
display->cursor_visible++;
context_enable_timer(display->ctx);
if (verbose & CURSOR) {
int x, y;
printf("%s cursor image %dx%d, serial %d:\n",
DisplayString(display->dpy),
cur->width, cur->height,
display->cursor_serial);
dst = display->cursor_image.pixels;
for (y = 0; y < cur->height; y++) {
for (x = 0; x < cur->width; x++) {
if (x == cur->xhot && y == cur->yhot)
printf("+");
else
printf("%c", *dst ? *dst >> 24 >= 127 ? 'x' : '.' : ' ');
dst++;
}
printf("\n");
}
}
}
@ -1700,6 +1716,8 @@ static void display_flush_cursor(struct display *display)
if (cursor == None)
cursor = display->invisible_cursor;
if (cursor != display->cursor) {
DBG(CURSOR, ("%s setting cursor shape %lx\n",
DisplayString(display->dpy), (long)cursor));
XDefineCursor(display->dpy, display->root, cursor);
display->cursor = cursor;
}
@ -3405,8 +3423,17 @@ int main(int argc, char **argv)
if (cur == NULL)
continue;
for (i = 1; i < ctx.ndisplay; i++)
display_load_visible_cursor(&ctx.display[i], cur);
display_load_visible_cursor(&ctx.display[0], cur);
for (i = 1; i < ctx.ndisplay; i++) {
struct display *display = &ctx.display[i];
DBG(CURSOR, ("%s marking cursor changed\n", DisplayString(display->dpy)));
display->cursor_moved++;
if (display->cursor != display->invisible_cursor) {
display->cursor_visible++;
context_enable_timer(display->ctx);
}
}
XFree(cur);
} else if (e.type == ctx.display->rr_event + RRScreenChangeNotify) {