• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2009 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 
29 /**
30  * Scene queue.  We'll use two queues.  One contains "full" scenes which
31  * are produced by the "setup" code.  The other contains "empty" scenes
32  * which are produced by the "rast" code when it finishes rendering a scene.
33  */
34 
35 #include "os/os_thread.h"
36 #include "util/u_memory.h"
37 #include "lp_scene_queue.h"
38 #include "util/u_math.h"
39 
40 
41 
42 #define SCENE_QUEUE_SIZE 4
43 
44 
45 
46 /**
47  * A queue of scenes
48  */
49 struct lp_scene_queue
50 {
51    struct lp_scene *scenes[SCENE_QUEUE_SIZE];
52 
53    mtx_t mutex;
54    cnd_t change;
55 
56    /* These values wrap around, so that head == tail means empty.  When used
57     * to index the array, we use them modulo the queue size.  This scheme
58     * works because the queue size is a power of two.
59     */
60    unsigned head;
61    unsigned tail;
62 };
63 
64 
65 
66 /** Allocate a new scene queue */
67 struct lp_scene_queue *
lp_scene_queue_create(void)68 lp_scene_queue_create(void)
69 {
70    /* Circular queue behavior depends on size being a power of two. */
71    STATIC_ASSERT(SCENE_QUEUE_SIZE > 0);
72    STATIC_ASSERT((SCENE_QUEUE_SIZE & (SCENE_QUEUE_SIZE - 1)) == 0);
73 
74    struct lp_scene_queue *queue = CALLOC_STRUCT(lp_scene_queue);
75 
76    if (!queue)
77       return NULL;
78 
79    (void) mtx_init(&queue->mutex, mtx_plain);
80    cnd_init(&queue->change);
81 
82    return queue;
83 }
84 
85 
86 /** Delete a scene queue */
87 void
lp_scene_queue_destroy(struct lp_scene_queue * queue)88 lp_scene_queue_destroy(struct lp_scene_queue *queue)
89 {
90    cnd_destroy(&queue->change);
91    mtx_destroy(&queue->mutex);
92    FREE(queue);
93 }
94 
95 
96 /** Remove first lp_scene from head of queue */
97 struct lp_scene *
lp_scene_dequeue(struct lp_scene_queue * queue,boolean wait)98 lp_scene_dequeue(struct lp_scene_queue *queue, boolean wait)
99 {
100    mtx_lock(&queue->mutex);
101 
102    if (wait) {
103       /* Wait for queue to be not empty. */
104       while (queue->head == queue->tail)
105          cnd_wait(&queue->change, &queue->mutex);
106    } else {
107       if (queue->head == queue->tail) {
108          mtx_unlock(&queue->mutex);
109          return NULL;
110       }
111    }
112 
113    struct lp_scene *scene = queue->scenes[queue->head++ % SCENE_QUEUE_SIZE];
114 
115    cnd_signal(&queue->change);
116    mtx_unlock(&queue->mutex);
117 
118    return scene;
119 }
120 
121 
122 /** Add an lp_scene to tail of queue */
123 void
lp_scene_enqueue(struct lp_scene_queue * queue,struct lp_scene * scene)124 lp_scene_enqueue(struct lp_scene_queue *queue, struct lp_scene *scene)
125 {
126    mtx_lock(&queue->mutex);
127 
128    /* Wait for free space. */
129    while (queue->tail - queue->head >= SCENE_QUEUE_SIZE)
130       cnd_wait(&queue->change, &queue->mutex);
131 
132    queue->scenes[queue->tail++ % SCENE_QUEUE_SIZE] = scene;
133 
134    cnd_signal(&queue->change);
135    mtx_unlock(&queue->mutex);
136 }
137