cell: support for cubemaps
[mesa.git] / src / gallium / drivers / cell / ppu / cell_state_emit.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_inlines.h"
29 #include "util/u_memory.h"
30 #include "cell_context.h"
31 #include "cell_gen_fragment.h"
32 #include "cell_state.h"
33 #include "cell_state_emit.h"
34 #include "cell_batch.h"
35 #include "cell_texture.h"
36 #include "draw/draw_context.h"
37 #include "draw/draw_private.h"
38
39
40 /**
41 * Find/create a cell_command_fragment_ops object corresponding to the
42 * current blend/stencil/z/colormask/etc. state.
43 */
44 static struct cell_command_fragment_ops *
45 lookup_fragment_ops(struct cell_context *cell)
46 {
47 struct cell_fragment_ops_key key;
48 struct cell_command_fragment_ops *ops;
49
50 /*
51 * Build key
52 */
53 memset(&key, 0, sizeof(key));
54 key.blend = *cell->blend;
55 key.dsa = *cell->depth_stencil;
56
57 if (cell->framebuffer.cbufs[0])
58 key.color_format = cell->framebuffer.cbufs[0]->format;
59 else
60 key.color_format = PIPE_FORMAT_NONE;
61
62 if (cell->framebuffer.zsbuf)
63 key.zs_format = cell->framebuffer.zsbuf->format;
64 else
65 key.zs_format = PIPE_FORMAT_NONE;
66
67 /*
68 * Look up key in cache.
69 */
70 ops = (struct cell_command_fragment_ops *)
71 util_keymap_lookup(cell->fragment_ops_cache, &key);
72
73 /*
74 * If not found, create/save new fragment ops command.
75 */
76 if (!ops) {
77 struct spe_function spe_code;
78
79 if (0)
80 debug_printf("**** Create New Fragment Ops\n");
81
82 /* Prepare the buffer that will hold the generated code. */
83 spe_init_func(&spe_code, SPU_MAX_FRAGMENT_OPS_INSTS * SPE_INST_SIZE);
84
85 /* generate new code */
86 cell_gen_fragment_function(cell, &spe_code);
87
88 /* alloc new fragment ops command */
89 ops = CALLOC_STRUCT(cell_command_fragment_ops);
90
91 /* populate the new cell_command_fragment_ops object */
92 ops->opcode = CELL_CMD_STATE_FRAGMENT_OPS;
93 memcpy(ops->code, spe_code.store, spe_code_size(&spe_code));
94 ops->dsa = *cell->depth_stencil;
95 ops->blend = *cell->blend;
96
97 /* insert cell_command_fragment_ops object into keymap/cache */
98 util_keymap_insert(cell->fragment_ops_cache, &key, ops, NULL);
99
100 /* release rtasm buffer */
101 spe_release_func(&spe_code);
102 }
103 else {
104 if (0)
105 debug_printf("**** Re-use Fragment Ops\n");
106 }
107
108 return ops;
109 }
110
111
112
113 static void
114 emit_state_cmd(struct cell_context *cell, uint cmd,
115 const void *state, uint state_size)
116 {
117 uint64_t *dst = (uint64_t *)
118 cell_batch_alloc(cell, ROUNDUP8(sizeof(uint64_t) + state_size));
119 *dst = cmd;
120 memcpy(dst + 1, state, state_size);
121 }
122
123
124 /**
125 * For state marked as 'dirty', construct a state-update command block
126 * and insert it into the current batch buffer.
127 */
128 void
129 cell_emit_state(struct cell_context *cell)
130 {
131 if (cell->dirty & CELL_NEW_FRAMEBUFFER) {
132 struct pipe_surface *cbuf = cell->framebuffer.cbufs[0];
133 struct pipe_surface *zbuf = cell->framebuffer.zsbuf;
134 struct cell_command_framebuffer *fb
135 = cell_batch_alloc(cell, sizeof(*fb));
136 fb->opcode = CELL_CMD_STATE_FRAMEBUFFER;
137 fb->color_start = cell->cbuf_map[0];
138 fb->color_format = cbuf->format;
139 fb->depth_start = cell->zsbuf_map;
140 fb->depth_format = zbuf ? zbuf->format : PIPE_FORMAT_NONE;
141 fb->width = cell->framebuffer.width;
142 fb->height = cell->framebuffer.height;
143 #if 0
144 printf("EMIT color format %s\n", pf_name(fb->color_format));
145 printf("EMIT depth format %s\n", pf_name(fb->depth_format));
146 #endif
147 }
148
149 if (cell->dirty & (CELL_NEW_FS)) {
150 /* Send new fragment program to SPUs */
151 struct cell_command_fragment_program *fp
152 = cell_batch_alloc(cell, sizeof(*fp));
153 fp->opcode = CELL_CMD_STATE_FRAGMENT_PROGRAM;
154 fp->num_inst = cell->fs->code.num_inst;
155 memcpy(&fp->code, cell->fs->code.store,
156 SPU_MAX_FRAGMENT_PROGRAM_INSTS * SPE_INST_SIZE);
157 if (0) {
158 int i;
159 printf("PPU Emit CELL_CMD_STATE_FRAGMENT_PROGRAM:\n");
160 for (i = 0; i < fp->num_inst; i++) {
161 printf(" %3d: 0x%08x\n", i, fp->code[i]);
162 }
163 }
164 }
165
166 if (cell->dirty & (CELL_NEW_FS_CONSTANTS)) {
167 const uint shader = PIPE_SHADER_FRAGMENT;
168 const uint num_const = cell->constants[shader].size / sizeof(float);
169 uint i, j;
170 float *buf = cell_batch_alloc(cell, 16 + num_const * sizeof(float));
171 uint64_t *ibuf = (uint64_t *) buf;
172 const float *constants = pipe_buffer_map(cell->pipe.screen,
173 cell->constants[shader].buffer,
174 PIPE_BUFFER_USAGE_CPU_READ);
175 ibuf[0] = CELL_CMD_STATE_FS_CONSTANTS;
176 ibuf[1] = num_const;
177 j = 4;
178 for (i = 0; i < num_const; i++) {
179 buf[j++] = constants[i];
180 }
181 pipe_buffer_unmap(cell->pipe.screen, cell->constants[shader].buffer);
182 }
183
184 if (cell->dirty & (CELL_NEW_FRAMEBUFFER |
185 CELL_NEW_DEPTH_STENCIL |
186 CELL_NEW_BLEND)) {
187 struct cell_command_fragment_ops *fops, *fops_cmd;
188 fops_cmd = cell_batch_alloc(cell, sizeof(*fops_cmd));
189 fops = lookup_fragment_ops(cell);
190 memcpy(fops_cmd, fops, sizeof(*fops));
191 }
192
193 if (cell->dirty & CELL_NEW_SAMPLER) {
194 uint i;
195 for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
196 if (cell->sampler[i]) {
197 struct cell_command_sampler *sampler
198 = cell_batch_alloc(cell, sizeof(*sampler));
199 sampler->opcode = CELL_CMD_STATE_SAMPLER;
200 sampler->unit = i;
201 sampler->state = *cell->sampler[i];
202 }
203 }
204 }
205
206 if (cell->dirty & CELL_NEW_TEXTURE) {
207 uint i;
208 for (i = 0;i < CELL_MAX_SAMPLERS; i++) {
209 struct cell_command_texture *texture
210 = cell_batch_alloc(cell, sizeof(*texture));
211 texture->opcode = CELL_CMD_STATE_TEXTURE;
212 texture->unit = i;
213 if (cell->texture[i]) {
214 uint level;
215 for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) {
216 texture->start[level] = cell->texture[i]->tiled_data[level];
217 texture->width[level] = cell->texture[i]->base.width[level];
218 texture->height[level] = cell->texture[i]->base.height[level];
219 }
220 texture->target = cell->texture[i]->base.target;
221 }
222 else {
223 uint level;
224 for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) {
225 texture->start[level] = NULL;
226 texture->width[level] = 0;
227 texture->height[level] = 0;
228 }
229 texture->target = 0;
230 }
231 }
232 }
233
234 if (cell->dirty & CELL_NEW_VERTEX_INFO) {
235 emit_state_cmd(cell, CELL_CMD_STATE_VERTEX_INFO,
236 &cell->vertex_info, sizeof(struct vertex_info));
237 }
238
239 #if 0
240 if (cell->dirty & CELL_NEW_VS) {
241 const struct draw_context *const draw = cell->draw;
242 struct cell_shader_info info;
243
244 info.num_outputs = draw_num_vs_outputs(draw);
245 info.declarations = (uintptr_t) draw->vs.machine.Declarations;
246 info.num_declarations = draw->vs.machine.NumDeclarations;
247 info.instructions = (uintptr_t) draw->vs.machine.Instructions;
248 info.num_instructions = draw->vs.machine.NumInstructions;
249 info.immediates = (uintptr_t) draw->vs.machine.Imms;
250 info.num_immediates = draw->vs.machine.ImmLimit / 4;
251
252 emit_state_cmd(cell, CELL_CMD_STATE_BIND_VS, &info, sizeof(info));
253 }
254 #endif
255 }