summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/nouveau/nouveau_winsys.h6
-rw-r--r--src/gallium/drivers/nv30/nv30_context.c2
-rw-r--r--src/gallium/drivers/nv40/nv40_context.c3
-rw-r--r--src/gallium/drivers/nv40/nv40_context.h1
-rw-r--r--src/gallium/drivers/nv40/nv40_screen.h2
-rw-r--r--src/gallium/drivers/nv40/nv40_state_emit.c10
-rw-r--r--src/gallium/drivers/nv50/nv50_context.c2
-rw-r--r--src/gallium/winsys/dri/nouveau/nouveau_context.c63
-rw-r--r--src/gallium/winsys/dri/nouveau/nouveau_context.h8
-rw-r--r--src/gallium/winsys/dri/nouveau/nouveau_screen.h2
-rw-r--r--src/gallium/winsys/dri/nouveau/nouveau_winsys.c10
11 files changed, 94 insertions, 15 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h
index 11ca7e80dd..44c8bb919b 100644
--- a/src/gallium/drivers/nouveau/nouveau_winsys.h
+++ b/src/gallium/drivers/nouveau/nouveau_winsys.h
@@ -54,20 +54,20 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *,
unsigned chipset);
extern struct pipe_context *
-nv30_create(struct pipe_screen *);
+nv30_create(struct pipe_screen *, unsigned pctx_id);
extern struct pipe_screen *
nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *,
unsigned chipset);
extern struct pipe_context *
-nv40_create(struct pipe_screen *);
+nv40_create(struct pipe_screen *, unsigned pctx_id);
extern struct pipe_screen *
nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *,
unsigned chipset);
extern struct pipe_context *
-nv50_create(struct pipe_screen *);
+nv50_create(struct pipe_screen *, unsigned pctx_id);
#endif
diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c
index 522fb13226..28d3f057cc 100644
--- a/src/gallium/drivers/nv30/nv30_context.c
+++ b/src/gallium/drivers/nv30/nv30_context.c
@@ -265,7 +265,7 @@ nv30_init_hwctx(struct nv30_context *nv30, int rankine_class)
#define NV35TCL_CHIPSET_3X_MASK 0x000001e0
struct pipe_context *
-nv30_create(struct pipe_screen *screen)
+nv30_create(struct pipe_screen *screen, unsigned pctx_id)
{
struct pipe_winsys *pipe_winsys = screen->winsys;
struct nouveau_winsys *nvws = nv30_screen(screen)->nvws;
diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c
index 084829ce28..203c843a01 100644
--- a/src/gallium/drivers/nv40/nv40_context.c
+++ b/src/gallium/drivers/nv40/nv40_context.c
@@ -44,7 +44,7 @@ nv40_destroy(struct pipe_context *pipe)
}
struct pipe_context *
-nv40_create(struct pipe_screen *pscreen)
+nv40_create(struct pipe_screen *pscreen, unsigned pctx_id)
{
struct nv40_screen *screen = nv40_screen(pscreen);
struct pipe_winsys *ws = pscreen->winsys;
@@ -56,6 +56,7 @@ nv40_create(struct pipe_screen *pscreen)
if (!nv40)
return NULL;
nv40->screen = screen;
+ nv40->pctx_id = pctx_id;
nv40->chipset = chipset;
nv40->nvws = nvws;
diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h
index 3b669594dc..e118776306 100644
--- a/src/gallium/drivers/nv40/nv40_context.h
+++ b/src/gallium/drivers/nv40/nv40_context.h
@@ -108,6 +108,7 @@ struct nv40_context {
struct nouveau_winsys *nvws;
struct nv40_screen *screen;
+ unsigned pctx_id;
struct draw_context *draw;
diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h
index 9f9668dbb6..3ea78aadfd 100644
--- a/src/gallium/drivers/nv40/nv40_screen.h
+++ b/src/gallium/drivers/nv40/nv40_screen.h
@@ -9,6 +9,8 @@ struct nv40_screen {
struct nouveau_winsys *nvws;
unsigned chipset;
+ unsigned cur_pctx;
+
/* HW graphics objects */
struct nouveau_grobj *curie;
struct nouveau_notifier *sync;
diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c
index 221503617c..a95e2472e2 100644
--- a/src/gallium/drivers/nv40/nv40_state_emit.c
+++ b/src/gallium/drivers/nv40/nv40_state_emit.c
@@ -62,8 +62,18 @@ static void
nv40_state_emit(struct nv40_context *nv40)
{
struct nv40_state *state = &nv40->state;
+ struct nv40_screen *screen = nv40->screen;
unsigned i, samplers;
+ if (nv40->pctx_id != screen->cur_pctx) {
+ for (i = 0; i < NV40_STATE_MAX; i++) {
+ if (screen->state[i] != state->hw[i] && state->hw[i])
+ state->dirty |= (1ULL << i);
+ }
+
+ screen->cur_pctx = nv40->pctx_id;
+ }
+
while (state->dirty) {
unsigned idx = ffsll(state->dirty) - 1;
diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c
index e5054e34f6..c937b8de6d 100644
--- a/src/gallium/drivers/nv50/nv50_context.c
+++ b/src/gallium/drivers/nv50/nv50_context.c
@@ -56,7 +56,7 @@ nv50_init_hwctx(struct nv50_context *nv50, int tesla_class)
#define GRCLASS5097_CHIPSETS 0x00000000
#define GRCLASS8297_CHIPSETS 0x00000010
struct pipe_context *
-nv50_create(struct pipe_screen *pscreen)
+nv50_create(struct pipe_screen *pscreen, unsigned pctx_id)
{
struct pipe_winsys *pipe_winsys = pscreen->winsys;
struct nouveau_winsys *nvws = nv50_screen(pscreen)->nvws;
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_context.c b/src/gallium/winsys/dri/nouveau/nouveau_context.c
index 7915afae22..dc852c9f49 100644
--- a/src/gallium/winsys/dri/nouveau/nouveau_context.c
+++ b/src/gallium/winsys/dri/nouveau/nouveau_context.c
@@ -4,6 +4,7 @@
#include "utils.h"
#include "state_tracker/st_public.h"
+#include "state_tracker/st_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_context.h"
@@ -101,7 +102,8 @@ nouveau_context_create(const __GLcontextModes *glVis,
struct nouveau_device_priv *nvdev;
struct pipe_context *pipe = NULL;
struct st_context *st_share = NULL;
- int ret;
+ struct nouveau_channel_context *nvc = NULL;
+ int i, ret;
if (sharedContextPrivate) {
st_share = ((struct nouveau_context *)sharedContextPrivate)->st;
@@ -163,12 +165,56 @@ nouveau_context_create(const __GLcontextModes *glVis,
nv->frontbuffer = fb_surf;
}
- nv->nvc = nouveau_channel_context_create(&nvdev->base, nv->chipset);
- if (!nv->nvc) {
- NOUVEAU_ERR("Failed initialising GPU channel context\n");
- return GL_FALSE;
+ /* Attempt to share a single channel between multiple contexts from
+ * a single process.
+ */
+ nvc = nv_screen->nvc;
+ if (!nvc && st_share) {
+ struct nouveau_context *snv = st_share->pipe->priv;
+ if (snv) {
+ nvc = snv->nvc;
+ }
+ }
+
+ /*XXX: temporary - disable multi-context/single-channel on non-NV4x */
+ switch (nv->chipset & 0xf0) {
+ case 0x40:
+ case 0x60:
+ break;
+ default:
+ nvc = NULL;
+ break;
+ }
+
+ if (!nvc) {
+ nvc = nouveau_channel_context_create(&nvdev->base, nv->chipset);
+ if (!nvc) {
+ NOUVEAU_ERR("Failed initialising GPU context\n");
+ return GL_FALSE;
+ }
+ nv_screen->nvc = nvc;
+ }
+
+ nvc->refcount++;
+ nv->nvc = nvc;
+
+ /* Find a free slot for a pipe context, allocate a new one if needed */
+ nv->pctx_id = -1;
+ for (i = 0; i < nvc->nr_pctx; i++) {
+ if (nvc->pctx[i] == NULL) {
+ nv->pctx_id = i;
+ break;
+ }
}
+ if (nv->pctx_id < 0) {
+ nv->pctx_id = nvc->nr_pctx++;
+ nvc->pctx =
+ realloc(nvc->pctx,
+ sizeof(struct pipe_context *) * nvc->nr_pctx);
+ }
+
+ /* Create pipe */
if (nv->chipset < 0x50)
ret = nouveau_surface_init_nv04(nv);
else
@@ -201,13 +247,18 @@ void
nouveau_context_destroy(__DRIcontextPrivate *driContextPriv)
{
struct nouveau_context *nv = driContextPriv->driverPrivate;
+ struct nouveau_channel_context *nvc = nv->nvc;
assert(nv);
st_flush(nv->st, PIPE_FLUSH_WAIT);
st_destroy_context(nv->st);
- nouveau_channel_context_destroy(nv->nvc);
+ if (nv->pctx_id >= 0) {
+ nvc->pctx[nv->pctx_id] = NULL;
+ if (--nvc->refcount <= 0)
+ nouveau_channel_context_destroy(nvc);
+ }
free(nv);
}
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_context.h b/src/gallium/winsys/dri/nouveau/nouveau_context.h
index 736c8d8bef..92f551855a 100644
--- a/src/gallium/winsys/dri/nouveau/nouveau_context.h
+++ b/src/gallium/winsys/dri/nouveau/nouveau_context.h
@@ -14,6 +14,13 @@ struct nouveau_framebuffer {
};
struct nouveau_channel_context {
+ struct pipe_screen *pscreen;
+ int refcount;
+
+ unsigned cur_pctx;
+ unsigned nr_pctx;
+ struct pipe_context **pctx;
+
unsigned chipset;
struct nouveau_channel *channel;
@@ -51,6 +58,7 @@ struct nouveau_context {
/* Hardware context */
struct nouveau_channel_context *nvc;
+ int pctx_id;
/* pipe_surface accel */
struct pipe_surface *surf_src, *surf_dst;
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_screen.h b/src/gallium/winsys/dri/nouveau/nouveau_screen.h
index 019823bd44..e9da202690 100644
--- a/src/gallium/winsys/dri/nouveau/nouveau_screen.h
+++ b/src/gallium/winsys/dri/nouveau/nouveau_screen.h
@@ -14,6 +14,8 @@ struct nouveau_screen {
uint32_t front_pitch;
uint32_t front_cpp;
uint32_t front_height;
+
+ void *nvc;
};
#endif
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys.c b/src/gallium/winsys/dri/nouveau/nouveau_winsys.c
index 50d7549b1b..87619bdcfb 100644
--- a/src/gallium/winsys/dri/nouveau/nouveau_winsys.c
+++ b/src/gallium/winsys/dri/nouveau/nouveau_winsys.c
@@ -70,11 +70,12 @@ nouveau_pipe_emit_reloc(struct nouveau_channel *chan, void *ptr,
struct pipe_context *
nouveau_pipe_create(struct nouveau_context *nv)
{
+ struct nouveau_channel_context *nvc = nv->nvc;
struct nouveau_winsys *nvws = CALLOC_STRUCT(nouveau_winsys);
struct pipe_screen *(*hws_create)(struct pipe_winsys *,
struct nouveau_winsys *,
unsigned chipset);
- struct pipe_context *(*hw_create)(struct pipe_screen *);
+ struct pipe_context *(*hw_create)(struct pipe_screen *, unsigned);
struct pipe_winsys *ws;
struct pipe_screen *pscreen;
@@ -125,7 +126,10 @@ nouveau_pipe_create(struct nouveau_context *nv)
nvws->surface_fill = nouveau_pipe_surface_fill;
ws = nouveau_create_pipe_winsys(nv);
- pscreen = hws_create(ws, nvws, nv->chipset);
- return hw_create(pscreen);
+
+ if (!nvc->pscreen)
+ nvc->pscreen = hws_create(ws, nvws, nv->chipset);
+ nvc->pctx[nv->pctx_id] = hw_create(nvc->pscreen, nv->pctx_id);
+ return nvc->pctx[nv->pctx_id];
}