static int thread_rendering;
static BOOL hold_cmds;
static BOOL needs_display;
+static BOOL flushed;
extern const unsigned char cmd_lengths[];
tmp = thread.queue;
thread.queue = thread.bg_queue;
thread.bg_queue = tmp;
- needs_display = TRUE;
pthread_cond_signal(&thread.cond_msg_avail);
}
pthread_mutex_unlock(&thread.queue_lock);
return;
}
+ if (thread.bg_queue->used) {
+ /* When we flush the background queue, the vblank handler can't
+ * know that we had a frame pending, and we delay rendering too
+ * long. Force it. */
+ flushed = TRUE;
+ }
+
/* Flush both queues. This is necessary because gpulib could be
* trying to process a DMA write that a command in the queue should
* run beforehand. For example, Xenogears sprites write a black
}
pthread_mutex_lock(&thread.queue_lock);
- if (thread.bg_queue->used) {
+ if (thread.bg_queue->used || flushed) {
/* We have commands for a future frame to run. Force a wait until
* the current frame is finished, and start processing the next
* frame after it's drawn (see the `updated` clause above). */
/* We are no longer holding commands back, so the next frame may
* get mixed into the following frame. This is usually fine, but can
* result in frameskip-like effects for 60fps games. */
+ flushed = FALSE;
hold_cmds = FALSE;
needs_display = TRUE;
gpu.state.fb_dirty = TRUE;