Merge remote branch 'origin/7.8'
[mesa.git] / src / gallium / drivers / cell / ppu / cell_state_shader.c
1 /**************************************************************************
2 *
3 * Copyright 2007 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 "pipe/p_defines.h"
29 #include "util/u_memory.h"
30 #include "util/u_inlines.h"
31 #include "draw/draw_context.h"
32 #include "tgsi/tgsi_parse.h"
33
34 #include "cell_context.h"
35 #include "cell_state.h"
36 #include "cell_gen_fp.h"
37 #include "cell_buffer.h"
38
39
40 /** cast wrapper */
41 static INLINE struct cell_fragment_shader_state *
42 cell_fragment_shader_state(void *shader)
43 {
44 return (struct cell_fragment_shader_state *) shader;
45 }
46
47
48 /** cast wrapper */
49 static INLINE struct cell_vertex_shader_state *
50 cell_vertex_shader_state(void *shader)
51 {
52 return (struct cell_vertex_shader_state *) shader;
53 }
54
55
56 /**
57 * Create fragment shader state.
58 * Called via pipe->create_fs_state()
59 */
60 static void *
61 cell_create_fs_state(struct pipe_context *pipe,
62 const struct pipe_shader_state *templ)
63 {
64 struct cell_context *cell = cell_context(pipe);
65 struct cell_fragment_shader_state *cfs;
66
67 cfs = CALLOC_STRUCT(cell_fragment_shader_state);
68 if (!cfs)
69 return NULL;
70
71 cfs->shader.tokens = tgsi_dup_tokens(templ->tokens);
72 if (!cfs->shader.tokens) {
73 FREE(cfs);
74 return NULL;
75 }
76
77 tgsi_scan_shader(templ->tokens, &cfs->info);
78
79 cell_gen_fragment_program(cell, cfs->shader.tokens, &cfs->code);
80
81 return cfs;
82 }
83
84
85 /**
86 * Called via pipe->bind_fs_state()
87 */
88 static void
89 cell_bind_fs_state(struct pipe_context *pipe, void *fs)
90 {
91 struct cell_context *cell = cell_context(pipe);
92
93 cell->fs = cell_fragment_shader_state(fs);
94
95 cell->dirty |= CELL_NEW_FS;
96 }
97
98
99 /**
100 * Called via pipe->delete_fs_state()
101 */
102 static void
103 cell_delete_fs_state(struct pipe_context *pipe, void *fs)
104 {
105 struct cell_fragment_shader_state *cfs = cell_fragment_shader_state(fs);
106
107 spe_release_func(&cfs->code);
108
109 FREE((void *) cfs->shader.tokens);
110 FREE(cfs);
111 }
112
113
114 /**
115 * Create vertex shader state.
116 * Called via pipe->create_vs_state()
117 */
118 static void *
119 cell_create_vs_state(struct pipe_context *pipe,
120 const struct pipe_shader_state *templ)
121 {
122 struct cell_context *cell = cell_context(pipe);
123 struct cell_vertex_shader_state *cvs;
124
125 cvs = CALLOC_STRUCT(cell_vertex_shader_state);
126 if (!cvs)
127 return NULL;
128
129 cvs->shader.tokens = tgsi_dup_tokens(templ->tokens);
130 if (!cvs->shader.tokens) {
131 FREE(cvs);
132 return NULL;
133 }
134
135 tgsi_scan_shader(templ->tokens, &cvs->info);
136
137 cvs->draw_data = draw_create_vertex_shader(cell->draw, &cvs->shader);
138 if (cvs->draw_data == NULL) {
139 FREE( (void *) cvs->shader.tokens );
140 FREE( cvs );
141 return NULL;
142 }
143
144 return cvs;
145 }
146
147
148 /**
149 * Called via pipe->bind_vs_state()
150 */
151 static void
152 cell_bind_vs_state(struct pipe_context *pipe, void *vs)
153 {
154 struct cell_context *cell = cell_context(pipe);
155
156 cell->vs = cell_vertex_shader_state(vs);
157
158 draw_bind_vertex_shader(cell->draw,
159 (cell->vs ? cell->vs->draw_data : NULL));
160
161 cell->dirty |= CELL_NEW_VS;
162 }
163
164
165 /**
166 * Called via pipe->delete_vs_state()
167 */
168 static void
169 cell_delete_vs_state(struct pipe_context *pipe, void *vs)
170 {
171 struct cell_context *cell = cell_context(pipe);
172 struct cell_vertex_shader_state *cvs = cell_vertex_shader_state(vs);
173
174 draw_delete_vertex_shader(cell->draw, cvs->draw_data);
175 FREE( (void *) cvs->shader.tokens );
176 FREE( cvs );
177 }
178
179
180 /**
181 * Called via pipe->set_constant_buffer()
182 */
183 static void
184 cell_set_constant_buffer(struct pipe_context *pipe,
185 uint shader, uint index,
186 struct pipe_buffer *constants)
187 {
188 struct cell_context *cell = cell_context(pipe);
189 unsigned size = constants ? constants->size : 0;
190 const void *data = constants ? cell_buffer(constants)->data : NULL;
191
192 assert(shader < PIPE_SHADER_TYPES);
193 assert(index == 0);
194
195 if (cell->constants[shader] == constants)
196 return;
197
198 draw_flush(cell->draw);
199
200 /* note: reference counting */
201 pipe_buffer_reference(&cell->constants[shader], constants);
202
203 if(shader == PIPE_SHADER_VERTEX) {
204 draw_set_mapped_constant_buffer(cell->draw, PIPE_SHADER_VERTEX, 0,
205 data, size);
206 }
207
208 cell->mapped_constants[shader] = data;
209
210 if (shader == PIPE_SHADER_VERTEX)
211 cell->dirty |= CELL_NEW_VS_CONSTANTS;
212 else if (shader == PIPE_SHADER_FRAGMENT)
213 cell->dirty |= CELL_NEW_FS_CONSTANTS;
214 }
215
216
217 void
218 cell_init_shader_functions(struct cell_context *cell)
219 {
220 cell->pipe.create_fs_state = cell_create_fs_state;
221 cell->pipe.bind_fs_state = cell_bind_fs_state;
222 cell->pipe.delete_fs_state = cell_delete_fs_state;
223
224 cell->pipe.create_vs_state = cell_create_vs_state;
225 cell->pipe.bind_vs_state = cell_bind_vs_state;
226 cell->pipe.delete_vs_state = cell_delete_vs_state;
227
228 cell->pipe.set_constant_buffer = cell_set_constant_buffer;
229 }