cell: checkpoint commit of new per-fragment processing
[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 "util/u_memory.h"
29 #include "cell_context.h"
30 #include "cell_gen_fragment.h"
31 #include "cell_state.h"
32 #include "cell_state_emit.h"
33 #include "cell_state_per_fragment.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 static void
41 emit_state_cmd(struct cell_context *cell, uint cmd,
42 const void *state, uint state_size)
43 {
44 uint64_t *dst = (uint64_t *)
45 cell_batch_alloc(cell, ROUNDUP8(sizeof(uint64_t) + state_size));
46 *dst = cmd;
47 memcpy(dst + 1, state, state_size);
48 }
49
50
51 /**
52 * For state marked as 'dirty', construct a state-update command block
53 * and insert it into the current batch buffer.
54 */
55 void
56 cell_emit_state(struct cell_context *cell)
57 {
58 if (cell->dirty & (CELL_NEW_FRAMEBUFFER | CELL_NEW_BLEND)) {
59 struct cell_command_logicop logicop;
60
61 if (cell->logic_op.store != NULL) {
62 spe_release_func(& cell->logic_op);
63 }
64
65 cell_generate_logic_op(& cell->logic_op,
66 & cell->blend->base,
67 cell->framebuffer.cbufs[0]);
68
69 logicop.base = (intptr_t) cell->logic_op.store;
70 logicop.size = 64 * 4;
71 emit_state_cmd(cell, CELL_CMD_STATE_LOGICOP, &logicop,
72 sizeof(logicop));
73 }
74
75 if (cell->dirty & CELL_NEW_FRAMEBUFFER) {
76 struct pipe_surface *cbuf = cell->framebuffer.cbufs[0];
77 struct pipe_surface *zbuf = cell->framebuffer.zsbuf;
78 struct cell_command_framebuffer *fb
79 = cell_batch_alloc(cell, sizeof(*fb));
80 fb->opcode = CELL_CMD_STATE_FRAMEBUFFER;
81 fb->color_start = cell->cbuf_map[0];
82 fb->color_format = cbuf->format;
83 fb->depth_start = cell->zsbuf_map;
84 fb->depth_format = zbuf ? zbuf->format : PIPE_FORMAT_NONE;
85 fb->width = cell->framebuffer.width;
86 fb->height = cell->framebuffer.height;
87 #if 0
88 printf("EMIT color format %s\n", pf_name(fb->color_format));
89 printf("EMIT depth format %s\n", pf_name(fb->depth_format));
90 #endif
91 }
92
93
94 if (cell->dirty & (CELL_NEW_FRAMEBUFFER | CELL_NEW_DEPTH_STENCIL)) {
95 /* XXX we don't want to always do codegen here. We should have
96 * a hash/lookup table to cache previous results...
97 */
98 struct cell_command_fragment_ops *fops
99 = cell_batch_alloc(cell, sizeof(*fops));
100 struct spe_function spe_code;
101
102 /* generate new code */
103 gen_fragment_function(cell, &spe_code);
104 /* put the new code into the batch buffer */
105 fops->opcode = CELL_CMD_STATE_FRAGMENT_OPS;
106 memcpy(&fops->code, spe_code.store,
107 SPU_MAX_FRAGMENT_OPS_INSTS * SPE_INST_SIZE);
108 /* free codegen buffer */
109 spe_release_func(&spe_code);
110 }
111
112 if (cell->dirty & CELL_NEW_BLEND) {
113 struct cell_command_blend blend;
114
115 if (cell->blend != NULL) {
116 blend.base = (intptr_t) cell->blend->code.store;
117 blend.size = cell->blend->code.num_inst * SPE_INST_SIZE;
118 blend.read_fb = TRUE;
119 }
120 else {
121 blend.base = 0;
122 blend.size = 0;
123 blend.read_fb = FALSE;
124 }
125
126 emit_state_cmd(cell, CELL_CMD_STATE_BLEND, &blend, sizeof(blend));
127 }
128
129 if (cell->dirty & CELL_NEW_DEPTH_STENCIL) {
130 struct cell_command_depth_stencil_alpha_test dsat;
131
132 if (cell->depth_stencil != NULL) {
133 dsat.base = (intptr_t) cell->depth_stencil->code.store;
134 dsat.size = cell->depth_stencil->code.num_inst * SPE_INST_SIZE;
135 dsat.read_depth = TRUE;
136 dsat.read_stencil = FALSE;
137 dsat.state = cell->depth_stencil->base;
138 }
139 else {
140 dsat.base = 0;
141 dsat.size = 0;
142 dsat.read_depth = FALSE;
143 dsat.read_stencil = FALSE;
144 }
145
146 emit_state_cmd(cell, CELL_CMD_STATE_DEPTH_STENCIL, &dsat, sizeof(dsat));
147 }
148
149 if (cell->dirty & CELL_NEW_SAMPLER) {
150 uint i;
151 for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
152 if (cell->sampler[i]) {
153 struct cell_command_sampler *sampler
154 = cell_batch_alloc(cell, sizeof(*sampler));
155 sampler->opcode = CELL_CMD_STATE_SAMPLER;
156 sampler->unit = i;
157 sampler->state = *cell->sampler[i];
158 }
159 }
160 }
161
162 if (cell->dirty & CELL_NEW_TEXTURE) {
163 uint i;
164 for (i = 0;i < CELL_MAX_SAMPLERS; i++) {
165 struct cell_command_texture *texture
166 = cell_batch_alloc(cell, sizeof(*texture));
167 texture->opcode = CELL_CMD_STATE_TEXTURE;
168 texture->unit = i;
169 if (cell->texture[i]) {
170 texture->start = cell->texture[i]->tiled_data;
171 texture->width = cell->texture[i]->base.width[0];
172 texture->height = cell->texture[i]->base.height[0];
173 }
174 else {
175 texture->start = NULL;
176 texture->width = 1;
177 texture->height = 1;
178 }
179 }
180 }
181
182 if (cell->dirty & CELL_NEW_VERTEX_INFO) {
183 emit_state_cmd(cell, CELL_CMD_STATE_VERTEX_INFO,
184 &cell->vertex_info, sizeof(struct vertex_info));
185 }
186
187 if (cell->dirty & CELL_NEW_VS) {
188 const struct draw_context *const draw = cell->draw;
189 struct cell_shader_info info;
190
191 info.num_outputs = draw_num_vs_outputs(draw);
192 info.declarations = (uintptr_t) draw->vs.machine.Declarations;
193 info.num_declarations = draw->vs.machine.NumDeclarations;
194 info.instructions = (uintptr_t) draw->vs.machine.Instructions;
195 info.num_instructions = draw->vs.machine.NumInstructions;
196 info.immediates = (uintptr_t) draw->vs.machine.Imms;
197 info.num_immediates = draw->vs.machine.ImmLimit / 4;
198
199 emit_state_cmd(cell, CELL_CMD_STATE_BIND_VS, &info, sizeof(info));
200 }
201 }