Path: blob/21.2-virgl/src/gallium/drivers/llvmpipe/lp_scene_queue.c
4570 views
/**************************************************************************1*2* Copyright 2009 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/262728/**29* Scene queue. We'll use two queues. One contains "full" scenes which30* are produced by the "setup" code. The other contains "empty" scenes31* which are produced by the "rast" code when it finishes rendering a scene.32*/3334#include "os/os_thread.h"35#include "util/u_memory.h"36#include "lp_scene_queue.h"37#include "util/u_math.h"38394041#define SCENE_QUEUE_SIZE 442434445/**46* A queue of scenes47*/48struct lp_scene_queue49{50struct lp_scene *scenes[SCENE_QUEUE_SIZE];5152mtx_t mutex;53cnd_t change;5455/* These values wrap around, so that head == tail means empty. When used56* to index the array, we use them modulo the queue size. This scheme57* works because the queue size is a power of two.58*/59unsigned head;60unsigned tail;61};62636465/** Allocate a new scene queue */66struct lp_scene_queue *67lp_scene_queue_create(void)68{69/* Circular queue behavior depends on size being a power of two. */70STATIC_ASSERT(SCENE_QUEUE_SIZE > 0);71STATIC_ASSERT((SCENE_QUEUE_SIZE & (SCENE_QUEUE_SIZE - 1)) == 0);7273struct lp_scene_queue *queue = CALLOC_STRUCT(lp_scene_queue);7475if (!queue)76return NULL;7778(void) mtx_init(&queue->mutex, mtx_plain);79cnd_init(&queue->change);8081return queue;82}838485/** Delete a scene queue */86void87lp_scene_queue_destroy(struct lp_scene_queue *queue)88{89cnd_destroy(&queue->change);90mtx_destroy(&queue->mutex);91FREE(queue);92}939495/** Remove first lp_scene from head of queue */96struct lp_scene *97lp_scene_dequeue(struct lp_scene_queue *queue, boolean wait)98{99mtx_lock(&queue->mutex);100101if (wait) {102/* Wait for queue to be not empty. */103while (queue->head == queue->tail)104cnd_wait(&queue->change, &queue->mutex);105} else {106if (queue->head == queue->tail) {107mtx_unlock(&queue->mutex);108return NULL;109}110}111112struct lp_scene *scene = queue->scenes[queue->head++ % SCENE_QUEUE_SIZE];113114cnd_signal(&queue->change);115mtx_unlock(&queue->mutex);116117return scene;118}119120121/** Add an lp_scene to tail of queue */122void123lp_scene_enqueue(struct lp_scene_queue *queue, struct lp_scene *scene)124{125mtx_lock(&queue->mutex);126127/* Wait for free space. */128while (queue->tail - queue->head >= SCENE_QUEUE_SIZE)129cnd_wait(&queue->change, &queue->mutex);130131queue->scenes[queue->tail++ % SCENE_QUEUE_SIZE] = scene;132133cnd_signal(&queue->change);134mtx_unlock(&queue->mutex);135}136137138