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