Squashed commit of the following:
[profile/ivi/mesa.git] / src / gallium / drivers / cell / ppu / cell_fence.c
1 /**************************************************************************
2  * 
3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 #include <unistd.h>
29 #include "util/u_memory.h"
30 #include "util/u_inlines.h"
31 #include "cell_context.h"
32 #include "cell_batch.h"
33 #include "cell_fence.h"
34 #include "cell_texture.h"
35
36
37 void
38 cell_fence_init(struct cell_fence *fence)
39 {
40    uint i;
41    ASSERT_ALIGN16(fence->status);
42    for (i = 0; i < CELL_MAX_SPUS; i++) {
43       fence->status[i][0] = CELL_FENCE_IDLE;
44    }
45 }
46
47
48 boolean
49 cell_fence_signalled(const struct cell_context *cell,
50                      const struct cell_fence *fence)
51 {
52    uint i;
53    for (i = 0; i < cell->num_spus; i++) {
54       if (fence->status[i][0] != CELL_FENCE_SIGNALLED)
55          return FALSE;
56       /*assert(fence->status[i][0] == CELL_FENCE_EMITTED);*/
57    }
58    return TRUE;
59 }
60
61
62 void
63 cell_fence_finish(const struct cell_context *cell,
64                   const struct cell_fence *fence)
65 {
66    while (!cell_fence_signalled(cell, fence)) {
67       usleep(10);
68    }
69
70 #ifdef DEBUG
71    {
72       uint i;
73       for (i = 0; i < cell->num_spus; i++) {
74          assert(fence->status[i][0] == CELL_FENCE_SIGNALLED);
75       }
76    }
77 #endif
78 }
79
80
81
82
83 struct cell_buffer_node
84 {
85    struct pipe_resource *buffer;
86    struct cell_buffer_node *next;
87 };
88
89
90 static void
91 cell_add_buffer_to_list(struct cell_context *cell,
92                         struct cell_buffer_list *list,
93                         struct pipe_resource *buffer)
94 {
95    struct cell_buffer_node *node = CALLOC_STRUCT(cell_buffer_node);
96    /* create new list node which references the buffer, insert at head */
97    if (node) {
98       pipe_resource_reference(&node->buffer, buffer);
99       node->next = list->head;
100       list->head = node;
101    }
102 }
103
104
105 /**
106  * Wait for completion of the given fence, then unreference any buffers
107  * on the list.
108  * This typically unrefs/frees texture buffers after any rendering which uses
109  * them has completed.
110  */
111 void
112 cell_free_fenced_buffers(struct cell_context *cell,
113                          struct cell_buffer_list *list)
114 {
115    if (list->head) {
116       struct pipe_screen *ps = cell->pipe.screen;
117       struct cell_buffer_node *node;
118
119       cell_fence_finish(cell, &list->fence);
120
121       /* traverse the list, unreferencing buffers, freeing nodes */
122       node = list->head;
123       while (node) {
124          struct cell_buffer_node *next = node->next;
125          assert(node->buffer);
126          pipe_buffer_unmap(ps, node->buffer);
127 #if 0
128          printf("Unref buffer %p\n", node->buffer);
129          if (node->buffer->reference.count == 1)
130             printf("   Delete!\n");
131 #endif
132          pipe_resource_reference(&node->buffer, NULL);
133          FREE(node);
134          node = next;
135       }
136       list->head = NULL;
137    }
138 }
139
140
141 /**
142  * This should be called for each render command.
143  * Any texture buffers that are current bound will be added to a fenced
144  * list to be freed later when the fence is executed/signalled.
145  */
146 void
147 cell_add_fenced_textures(struct cell_context *cell)
148 {
149    struct cell_buffer_list *list = &cell->fenced_buffers[cell->cur_batch];
150    uint i;
151
152    for (i = 0; i < cell->num_textures; i++) {
153       struct cell_resource *ct = cell->texture[i];
154       if (ct) {
155 #if 0
156          printf("Adding texture %p buffer %p to list\n",
157                 ct, ct->tiled_buffer[level]);
158 #endif
159 #if 00
160          /* XXX this needs to be fixed/restored!
161           * Maybe keep pointers to textures, not buffers.
162           */
163          if (ct->base.buffer)
164             cell_add_buffer_to_list(cell, list, ct->buffer);
165 #endif
166       }
167    }
168 }