llvmpipe: Rasterize the quads according to what the blend function expects.
[mesa.git] / src / gallium / drivers / llvmpipe / lp_quad_blend.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 /**
29 * Quad blending.
30 *
31 * @author Jose Fonseca <jfonseca@vmware.com>
32 * @author Brian Paul
33 */
34
35 #include "pipe/p_defines.h"
36 #include "util/u_math.h"
37 #include "util/u_memory.h"
38 #include "util/u_debug_dump.h"
39 #include "lp_context.h"
40 #include "lp_state.h"
41 #include "lp_quad.h"
42 #include "lp_surface.h"
43 #include "lp_tile_cache.h"
44 #include "lp_tile_soa.h"
45 #include "lp_quad_pipe.h"
46
47
48 static void
49 logicop_quad(struct quad_stage *qs,
50 uint8_t src[][16],
51 uint8_t dst[][16])
52 {
53 struct llvmpipe_context *llvmpipe = qs->llvmpipe;
54 uint32_t *src4 = (uint32_t *) src;
55 uint32_t *dst4 = (uint32_t *) dst;
56 uint32_t *res4 = (uint32_t *) src;
57 uint j;
58
59 switch (llvmpipe->blend->base.logicop_func) {
60 case PIPE_LOGICOP_CLEAR:
61 for (j = 0; j < 4; j++)
62 res4[j] = 0;
63 break;
64 case PIPE_LOGICOP_NOR:
65 for (j = 0; j < 4; j++)
66 res4[j] = ~(src4[j] | dst4[j]);
67 break;
68 case PIPE_LOGICOP_AND_INVERTED:
69 for (j = 0; j < 4; j++)
70 res4[j] = ~src4[j] & dst4[j];
71 break;
72 case PIPE_LOGICOP_COPY_INVERTED:
73 for (j = 0; j < 4; j++)
74 res4[j] = ~src4[j];
75 break;
76 case PIPE_LOGICOP_AND_REVERSE:
77 for (j = 0; j < 4; j++)
78 res4[j] = src4[j] & ~dst4[j];
79 break;
80 case PIPE_LOGICOP_INVERT:
81 for (j = 0; j < 4; j++)
82 res4[j] = ~dst4[j];
83 break;
84 case PIPE_LOGICOP_XOR:
85 for (j = 0; j < 4; j++)
86 res4[j] = dst4[j] ^ src4[j];
87 break;
88 case PIPE_LOGICOP_NAND:
89 for (j = 0; j < 4; j++)
90 res4[j] = ~(src4[j] & dst4[j]);
91 break;
92 case PIPE_LOGICOP_AND:
93 for (j = 0; j < 4; j++)
94 res4[j] = src4[j] & dst4[j];
95 break;
96 case PIPE_LOGICOP_EQUIV:
97 for (j = 0; j < 4; j++)
98 res4[j] = ~(src4[j] ^ dst4[j]);
99 break;
100 case PIPE_LOGICOP_NOOP:
101 for (j = 0; j < 4; j++)
102 res4[j] = dst4[j];
103 break;
104 case PIPE_LOGICOP_OR_INVERTED:
105 for (j = 0; j < 4; j++)
106 res4[j] = ~src4[j] | dst4[j];
107 break;
108 case PIPE_LOGICOP_COPY:
109 for (j = 0; j < 4; j++)
110 res4[j] = src4[j];
111 break;
112 case PIPE_LOGICOP_OR_REVERSE:
113 for (j = 0; j < 4; j++)
114 res4[j] = src4[j] | ~dst4[j];
115 break;
116 case PIPE_LOGICOP_OR:
117 for (j = 0; j < 4; j++)
118 res4[j] = src4[j] | dst4[j];
119 break;
120 case PIPE_LOGICOP_SET:
121 for (j = 0; j < 4; j++)
122 res4[j] = ~0;
123 break;
124 default:
125 assert(0);
126 }
127 }
128
129
130 static void blend_begin(struct quad_stage *qs)
131 {
132 }
133
134
135 static void
136 blend_run(struct quad_stage *qs,
137 struct quad_header *quads[],
138 unsigned nr)
139 {
140 struct llvmpipe_context *llvmpipe = qs->llvmpipe;
141 struct lp_blend_state *blend = llvmpipe->blend;
142 unsigned cbuf;
143 uint q, i, j, k;
144
145 for (cbuf = 0; cbuf < llvmpipe->framebuffer.nr_cbufs; cbuf++)
146 {
147 unsigned x0 = quads[0]->input.x0;
148 unsigned y0 = quads[0]->input.y0;
149 uint8_t ALIGN16_ATTRIB src[4][16];
150 uint8_t ALIGN16_ATTRIB dst[4][16];
151 struct llvmpipe_cached_tile *tile
152 = lp_get_cached_tile(llvmpipe->cbuf_cache[cbuf], x0, y0);
153
154 assert(nr * QUAD_SIZE == TILE_VECTOR_HEIGHT * TILE_VECTOR_WIDTH);
155
156 assert(x0 % TILE_VECTOR_WIDTH == 0);
157 assert(y0 % TILE_VECTOR_HEIGHT == 0);
158
159 for (q = 0; q < nr; q += 4) {
160 for (k = 0; k < 4 && q + k < nr; ++k) {
161 struct quad_header *quad = quads[q + k];
162 const int itx = (quad->input.x0 & (TILE_SIZE-1));
163 const int ity = (quad->input.y0 & (TILE_SIZE-1));
164
165 /* get/swizzle src/dest colors
166 */
167 for (j = 0; j < QUAD_SIZE; j++) {
168 int x = itx + (j & 1);
169 int y = ity + (j >> 1);
170 for (i = 0; i < 4; i++) {
171 src[i][4*k + j] = float_to_ubyte(quad->output.color[cbuf][i][j]);
172 dst[i][4*k + j] = TILE_PIXEL(tile->data.color, x, y, i);
173 }
174 }
175 }
176
177
178 if (blend->base.logicop_enable) {
179 logicop_quad( qs, src, dst );
180 }
181 else {
182 assert(blend->jit_function);
183 assert((((uintptr_t)src) & 0xf) == 0);
184 assert((((uintptr_t)dst) & 0xf) == 0);
185 assert((((uintptr_t)llvmpipe->blend_color) & 0xf) == 0);
186 if(blend->jit_function)
187 blend->jit_function( src, dst, llvmpipe->blend_color, src );
188 }
189
190 /* Output color values
191 */
192 for (k = 0; k < 4 && q + k < nr; ++k) {
193 struct quad_header *quad = quads[q + k];
194 const int itx = (quad->input.x0 & (TILE_SIZE-1));
195 const int ity = (quad->input.y0 & (TILE_SIZE-1));
196
197 for (j = 0; j < QUAD_SIZE; j++) {
198 if (quad->inout.mask & (1 << j)) {
199 int x = itx + (j & 1);
200 int y = ity + (j >> 1);
201 assert(x < TILE_SIZE);
202 assert(y < TILE_SIZE);
203 for (i = 0; i < 4; i++) { /* loop over color chans */
204 TILE_PIXEL(tile->data.color, x, y, i) = src[i][4*k + j];
205 }
206 }
207 }
208 }
209 }
210 }
211 }
212
213
214 static void blend_destroy(struct quad_stage *qs)
215 {
216 FREE( qs );
217 }
218
219
220 struct quad_stage *lp_quad_blend_stage( struct llvmpipe_context *llvmpipe )
221 {
222 struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
223
224 stage->llvmpipe = llvmpipe;
225 stage->begin = blend_begin;
226 stage->run = blend_run;
227 stage->destroy = blend_destroy;
228
229 return stage;
230 }