Keep track of damage event related flushes per-client v2

This further reduces the compositing slowdown due to flushing overhead,
by only flushing when the X server actually sends XDamageNotify events
to a client, and there hasn't been a flush yet in the meantime.

v2: Use ScreenPrivateKey, fixes invalid memory access with GPU screens
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Michel Dänzer
2016-07-11 12:51:46 +09:00
committed by Michel Dänzer
parent 9090309e05
commit 121a6de72d
2 changed files with 37 additions and 9 deletions

View File

@@ -448,6 +448,10 @@ struct radeon_accel_state {
Bool force;
};
struct radeon_client_priv {
uint_fast32_t needs_flush;
};
typedef struct {
EntityInfoPtr pEnt;
pciVideoPtr PciInfo;
@@ -474,7 +478,6 @@ typedef struct {
Bool allowColorTiling;
Bool allowColorTiling2D;
int callback_event_type;
uint_fast32_t callback_needs_flush;
uint_fast32_t gpu_flushed;
uint_fast32_t gpu_synced;
struct radeon_accel_state *accel_state;

View File

@@ -40,6 +40,7 @@
#include "radeon_version.h"
#include "shadow.h"
#include <xf86Priv.h>
#include "atipciids.h"
@@ -59,6 +60,8 @@
#include "radeon_cs_gem.h"
#include "radeon_vbo.h"
static DevScreenPrivateKeyRec radeon_client_private_key;
extern SymTabRec RADEONChipsets[];
static Bool radeon_setup_kernel_mem(ScreenPtr pScreen);
@@ -241,9 +244,9 @@ radeonUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
}
static Bool
callback_needs_flush(RADEONInfoPtr info)
callback_needs_flush(RADEONInfoPtr info, struct radeon_client_priv *client_priv)
{
return (int)(info->callback_needs_flush - info->gpu_flushed) > 0;
return (int)(client_priv->needs_flush - info->gpu_flushed) > 0;
}
static void
@@ -252,20 +255,30 @@ radeon_event_callback(CallbackListPtr *list,
{
EventInfoRec *eventinfo = call_data;
ScrnInfoPtr pScrn = user_data;
ScreenPtr pScreen = pScrn->pScreen;
struct radeon_client_priv *client_priv =
dixLookupScreenPrivate(&eventinfo->client->devPrivates,
&radeon_client_private_key, pScreen);
struct radeon_client_priv *server_priv =
dixLookupScreenPrivate(&serverClient->devPrivates,
&radeon_client_private_key, pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
int i;
if (callback_needs_flush(info))
if (callback_needs_flush(info, client_priv) ||
callback_needs_flush(info, server_priv))
return;
/* Don't let gpu_flushed get too far ahead of callback_needs_flush,
* in order to prevent false positives in callback_needs_flush()
/* Don't let gpu_flushed get too far ahead of needs_flush, in order
* to prevent false positives in callback_needs_flush()
*/
info->callback_needs_flush = info->gpu_flushed;
client_priv->needs_flush = info->gpu_flushed;
server_priv->needs_flush = info->gpu_flushed;
for (i = 0; i < eventinfo->count; i++) {
if (eventinfo->events[i].u.u.type == info->callback_event_type) {
info->callback_needs_flush++;
client_priv->needs_flush++;
server_priv->needs_flush++;
return;
}
}
@@ -276,9 +289,14 @@ radeon_flush_callback(CallbackListPtr *list,
pointer user_data, pointer call_data)
{
ScrnInfoPtr pScrn = user_data;
ScreenPtr pScreen = pScrn->pScreen;
ClientPtr client = call_data ? call_data : serverClient;
struct radeon_client_priv *client_priv =
dixLookupScreenPrivate(&client->devPrivates,
&radeon_client_private_key, pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
if (pScrn->vtSema && callback_needs_flush(info))
if (pScrn->vtSema && callback_needs_flush(info, client_priv))
radeon_cs_flush_indirect(pScrn);
}
@@ -351,6 +369,13 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
return FALSE;
}
if (!dixRegisterScreenPrivateKey(&radeon_client_private_key, pScreen,
PRIVATE_CLIENT, sizeof(struct radeon_client_priv))) {
DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
DeleteCallback(&EventCallback, radeon_event_callback, pScrn);
return FALSE;
}
}
return TRUE;