diff options
-rw-r--r-- | src/gallium/state_trackers/nine/nine_queue.c | 9 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/nine_queue.h | 3 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/nine_state.c | 67 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/nine_state.h | 12 |
4 files changed, 91 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/nine/nine_queue.c b/src/gallium/state_trackers/nine/nine_queue.c index 885b0ab6873..9f0bf8bad77 100644 --- a/src/gallium/state_trackers/nine/nine_queue.c +++ b/src/gallium/state_trackers/nine/nine_queue.c @@ -204,6 +204,15 @@ nine_queue_alloc(struct nine_queue_pool* ctx, unsigned space) return cmdbuf->mem_pool + offset; } +/* Returns the current queue flush state. + * TRUE nothing flushed + * FALSE one ore more instructions queued flushed. */ +bool +nine_queue_no_flushed_work(struct nine_queue_pool* ctx) +{ + return (ctx->tail == ctx->head); +} + /* Returns the current queue empty state. * TRUE no instructions queued. * FALSE one ore more instructions queued. */ diff --git a/src/gallium/state_trackers/nine/nine_queue.h b/src/gallium/state_trackers/nine/nine_queue.h index cc15bd853b4..52f6cbdfa87 100644 --- a/src/gallium/state_trackers/nine/nine_queue.h +++ b/src/gallium/state_trackers/nine/nine_queue.h @@ -40,6 +40,9 @@ void * nine_queue_alloc(struct nine_queue_pool* ctx, unsigned space); bool +nine_queue_no_flushed_work(struct nine_queue_pool* ctx); + +bool nine_queue_isempty(struct nine_queue_pool* ctx); struct nine_queue_pool* diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c index 9bb89e36764..c05d9bb18bd 100644 --- a/src/gallium/state_trackers/nine/nine_state.c +++ b/src/gallium/state_trackers/nine/nine_state.c @@ -66,6 +66,10 @@ struct csmt_context { pipe_mutex mutex_processed; struct NineDevice9 *device; BOOL processed; + BOOL toPause; + BOOL hasPaused; + pipe_mutex thread_running; + pipe_mutex thread_resume; }; /* Wait for instruction to be processed. @@ -93,6 +97,7 @@ PIPE_THREAD_ROUTINE(nine_csmt_worker, arg) while (1) { nine_queue_wait_flush(ctx->pool); + pipe_mutex_lock(ctx->thread_running); /* Get instruction. NULL on empty cmdbuf. */ while (!p_atomic_read(&ctx->terminate) && @@ -105,7 +110,16 @@ PIPE_THREAD_ROUTINE(nine_csmt_worker, arg) pipe_condvar_signal(ctx->event_processed); pipe_mutex_unlock(ctx->mutex_processed); } + if (p_atomic_read(&ctx->toPause)) { + pipe_mutex_unlock(ctx->thread_running); + /* will wait here the thread can be resumed */ + pipe_mutex_lock(ctx->thread_resume); + pipe_mutex_lock(ctx->thread_running); + pipe_mutex_unlock(ctx->thread_resume); + } } + + pipe_mutex_unlock(ctx->thread_running); if (p_atomic_read(&ctx->terminate)) { pipe_mutex_lock(ctx->mutex_processed); p_atomic_set(&ctx->processed, TRUE); @@ -138,6 +152,8 @@ nine_csmt_create( struct NineDevice9 *This ) } pipe_condvar_init(ctx->event_processed); pipe_mutex_init(ctx->mutex_processed); + pipe_mutex_init(ctx->thread_running); + pipe_mutex_init(ctx->thread_resume); #if DEBUG pipe_thread_setname("Main thread"); @@ -223,6 +239,43 @@ nine_csmt_destroy( struct NineDevice9 *device, struct csmt_context *ctx ) pipe_thread_wait(render_thread); } +static void +nine_csmt_pause( struct NineDevice9 *device ) +{ + struct csmt_context *ctx = device->csmt_ctx; + + if (!device->csmt_active) + return; + + /* No need to pause the thread */ + if (nine_queue_no_flushed_work(ctx->pool)) + return; + + pipe_mutex_lock(ctx->thread_resume); + p_atomic_set(&ctx->toPause, TRUE); + + /* Wait the thread is paused */ + pipe_mutex_lock(ctx->thread_running); + ctx->hasPaused = TRUE; + p_atomic_set(&ctx->toPause, FALSE); +} + +static void +nine_csmt_resume( struct NineDevice9 *device ) +{ + struct csmt_context *ctx = device->csmt_ctx; + + if (!device->csmt_active) + return; + + if (!ctx->hasPaused) + return; + + ctx->hasPaused = FALSE; + pipe_mutex_unlock(ctx->thread_running); + pipe_mutex_unlock(ctx->thread_resume); +} + struct pipe_context * nine_context_get_pipe( struct NineDevice9 *device ) { @@ -244,6 +297,20 @@ nine_context_get_pipe_multithread( struct NineDevice9 *device ) return device->context.pipe; } + +struct pipe_context * +nine_context_get_pipe_acquire( struct NineDevice9 *device ) +{ + nine_csmt_pause(device); + return device->context.pipe; +} + +void +nine_context_get_pipe_release( struct NineDevice9 *device ) +{ + nine_csmt_resume(device); +} + /* Nine state functions */ /* Check if some states need to be set dirty */ diff --git a/src/gallium/state_trackers/nine/nine_state.h b/src/gallium/state_trackers/nine/nine_state.h index 82ebcc9cbcd..912395de81f 100644 --- a/src/gallium/state_trackers/nine/nine_state.h +++ b/src/gallium/state_trackers/nine/nine_state.h @@ -600,4 +600,16 @@ nine_context_get_pipe( struct NineDevice9 *device ); struct pipe_context * nine_context_get_pipe_multithread( struct NineDevice9 *device ); + +/* Get the pipe_context (should not be called from the worker thread). + * All the work in the worker thread is paused before returning. + * It is neccessary to release in order to restart the thread. + * This is intended for use of the nine_context pipe_context that don't + * need the worker thread to finish all queued job. */ +struct pipe_context * +nine_context_get_pipe_acquire( struct NineDevice9 *device ); + +void +nine_context_get_pipe_release( struct NineDevice9 *device ); + #endif /* _NINE_STATE_H_ */ |