2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include "swrast_priv.h"
28 #define YFLIP(_xrb, Y) ((_xrb)->Base.Height - (Y) - 1)
31 * Dithering support takes the "computation" extreme in the "computation vs.
32 * storage" trade-off. This approach is very simple to implement and any
33 * computational overhead should be acceptable. XMesa uses table lookups for
34 * around 8KB of storage overhead per visual.
38 static const GLubyte kernel[16] = {
39 0*16, 8*16, 2*16, 10*16,
40 12*16, 4*16, 14*16, 6*16,
41 3*16, 11*16, 1*16, 9*16,
42 15*16, 7*16, 13*16, 5*16,
46 #define DITHER_COMP(X, Y) kernel[((X) & 0x3) | (((Y) & 0x3) << 2)]
48 #define DITHER_CLAMP(X) (((X) < CHAN_MAX) ? (X) : CHAN_MAX)
50 #define DITHER_COMP(X, Y) 0
52 #define DITHER_CLAMP(X) (X)
57 * Pixel macros shared across front/back buffer span functions.
61 #define STORE_PIXEL_A8R8G8B8(DST, X, Y, VALUE) \
62 *DST = VALUE[ACOMP] << 24 | VALUE[RCOMP] << 16 | VALUE[GCOMP] << 8 | VALUE[BCOMP]
63 #define STORE_PIXEL_RGB_A8R8G8B8(DST, X, Y, VALUE) \
64 *DST = 0xff << 24 | VALUE[RCOMP] << 16 | VALUE[GCOMP] << 8 | VALUE[BCOMP]
65 #define FETCH_PIXEL_A8R8G8B8(DST, SRC) \
66 DST[ACOMP] = *SRC >> 24; \
67 DST[RCOMP] = (*SRC >> 16) & 0xff; \
68 DST[GCOMP] = (*SRC >> 8) & 0xff; \
69 DST[BCOMP] = *SRC & 0xff
73 #define STORE_PIXEL_X8R8G8B8(DST, X, Y, VALUE) \
74 *DST = 0xff << 24 | VALUE[RCOMP] << 16 | VALUE[GCOMP] << 8 | VALUE[BCOMP]
75 #define STORE_PIXEL_RGB_X8R8G8B8(DST, X, Y, VALUE) \
76 *DST = 0xff << 24 | VALUE[RCOMP] << 16 | VALUE[GCOMP] << 8 | VALUE[BCOMP]
77 #define FETCH_PIXEL_X8R8G8B8(DST, SRC) \
79 DST[RCOMP] = (*SRC >> 16) & 0xff; \
80 DST[GCOMP] = (*SRC >> 8) & 0xff; \
81 DST[BCOMP] = *SRC & 0xff
85 #define STORE_PIXEL_R5G6B5(DST, X, Y, VALUE) \
87 int d = DITHER_COMP(X, Y) >> 6; \
88 *DST = ( ((DITHER_CLAMP((VALUE[RCOMP]) + d) & 0xf8) << 8) | \
89 ((DITHER_CLAMP((VALUE[GCOMP]) + d) & 0xfc) << 3) | \
90 ((DITHER_CLAMP((VALUE[BCOMP]) + d) & 0xf8) >> 3) ); \
92 #define FETCH_PIXEL_R5G6B5(DST, SRC) \
95 DST[RCOMP] = ((*SRC >> 8) & 0xf8) * 255 / 0xf8; \
96 DST[GCOMP] = ((*SRC >> 3) & 0xfc) * 255 / 0xfc; \
97 DST[BCOMP] = ((*SRC << 3) & 0xf8) * 255 / 0xf8; \
102 #define STORE_PIXEL_R3G3B2(DST, X, Y, VALUE) \
104 int d = DITHER_COMP(X, Y) >> 3; \
105 GLubyte *p = (GLubyte *)DST; \
106 *p = ( ((DITHER_CLAMP((VALUE[RCOMP]) + d) & 0xe0) >> 5) | \
107 ((DITHER_CLAMP((VALUE[GCOMP]) + d) & 0xe0) >> 2) | \
108 ((DITHER_CLAMP((VALUE[BCOMP]) + d) & 0xc0) >> 0) ); \
110 #define FETCH_PIXEL_R3G3B2(DST, SRC) \
112 GLubyte p = *(GLubyte *)SRC; \
114 DST[RCOMP] = ((p << 5) & 0xe0) * 255 / 0xe0; \
115 DST[GCOMP] = ((p << 2) & 0xe0) * 255 / 0xe0; \
116 DST[BCOMP] = ((p << 0) & 0xc0) * 255 / 0xc0; \
121 * Generate code for back-buffer span functions.
125 #define NAME(FUNC) FUNC##_A8R8G8B8
126 #define RB_TYPE GLubyte
128 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
129 #define INIT_PIXEL_PTR(P, X, Y) \
130 GLuint *P = (GLuint *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch / 4 + (X)
131 #define INC_PIXEL_PTR(P) P++
132 #define STORE_PIXEL(DST, X, Y, VALUE) \
133 STORE_PIXEL_A8R8G8B8(DST, X, Y, VALUE)
134 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
135 STORE_PIXEL_RGB_A8R8G8B8(DST, X, Y, VALUE)
136 #define FETCH_PIXEL(DST, SRC) \
137 FETCH_PIXEL_A8R8G8B8(DST, SRC)
139 #include "swrast/s_spantemp.h"
143 #define NAME(FUNC) FUNC##_X8R8G8B8
144 #define RB_TYPE GLubyte
146 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
147 #define INIT_PIXEL_PTR(P, X, Y) \
148 GLuint *P = (GLuint *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch / 4 + (X);
149 #define INC_PIXEL_PTR(P) P++
150 #define STORE_PIXEL(DST, X, Y, VALUE) \
151 STORE_PIXEL_X8R8G8B8(DST, X, Y, VALUE)
152 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
153 STORE_PIXEL_RGB_X8R8G8B8(DST, X, Y, VALUE)
154 #define FETCH_PIXEL(DST, SRC) \
155 FETCH_PIXEL_X8R8G8B8(DST, SRC)
157 #include "swrast/s_spantemp.h"
161 #define NAME(FUNC) FUNC##_R5G6B5
162 #define RB_TYPE GLubyte
164 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
165 #define INIT_PIXEL_PTR(P, X, Y) \
166 GLushort *P = (GLushort *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch / 2 + (X);
167 #define INC_PIXEL_PTR(P) P++
168 #define STORE_PIXEL(DST, X, Y, VALUE) \
169 STORE_PIXEL_R5G6B5(DST, X, Y, VALUE)
170 #define FETCH_PIXEL(DST, SRC) \
171 FETCH_PIXEL_R5G6B5(DST, SRC)
173 #include "swrast/s_spantemp.h"
177 #define NAME(FUNC) FUNC##_R3G3B2
178 #define RB_TYPE GLubyte
180 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
181 #define INIT_PIXEL_PTR(P, X, Y) \
182 GLubyte *P = (GLubyte *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch + (X) * 1;
183 #define INC_PIXEL_PTR(P) P += 1
184 #define STORE_PIXEL(DST, X, Y, VALUE) \
185 STORE_PIXEL_R3G3B2(DST, X, Y, VALUE)
186 #define FETCH_PIXEL(DST, SRC) \
187 FETCH_PIXEL_R3G3B2(DST, SRC)
189 #include "swrast/s_spantemp.h"
193 * Generate code for front-buffer span functions.
197 #define NAME(FUNC) FUNC##_A8R8G8B8_front
198 #define RB_TYPE GLubyte
200 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
201 #define INIT_PIXEL_PTR(P, X, Y) \
202 GLuint *P = (GLuint *)row;
203 #define INC_PIXEL_PTR(P) P++
204 #define STORE_PIXEL(DST, X, Y, VALUE) \
205 STORE_PIXEL_A8R8G8B8(DST, X, Y, VALUE)
206 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
207 STORE_PIXEL_RGB_A8R8G8B8(DST, X, Y, VALUE)
208 #define FETCH_PIXEL(DST, SRC) \
209 FETCH_PIXEL_A8R8G8B8(DST, SRC)
211 #include "swrast_spantemp.h"
215 #define NAME(FUNC) FUNC##_X8R8G8B8_front
216 #define RB_TYPE GLubyte
218 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
219 #define INIT_PIXEL_PTR(P, X, Y) \
220 GLuint *P = (GLuint *)row;
221 #define INC_PIXEL_PTR(P) P++
222 #define STORE_PIXEL(DST, X, Y, VALUE) \
223 STORE_PIXEL_X8R8G8B8(DST, X, Y, VALUE)
224 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
225 STORE_PIXEL_RGB_X8R8G8B8(DST, X, Y, VALUE)
226 #define FETCH_PIXEL(DST, SRC) \
227 FETCH_PIXEL_X8R8G8B8(DST, SRC)
229 #include "swrast_spantemp.h"
233 #define NAME(FUNC) FUNC##_R5G6B5_front
234 #define RB_TYPE GLubyte
236 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
237 #define INIT_PIXEL_PTR(P, X, Y) \
238 GLushort *P = (GLushort *)row;
239 #define INC_PIXEL_PTR(P) P++
240 #define STORE_PIXEL(DST, X, Y, VALUE) \
241 STORE_PIXEL_R5G6B5(DST, X, Y, VALUE)
242 #define FETCH_PIXEL(DST, SRC) \
243 FETCH_PIXEL_R5G6B5(DST, SRC)
245 #include "swrast_spantemp.h"
249 #define NAME(FUNC) FUNC##_R3G3B2_front
250 #define RB_TYPE GLubyte
252 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
253 #define INIT_PIXEL_PTR(P, X, Y) \
254 GLubyte *P = (GLubyte *)row;
255 #define INC_PIXEL_PTR(P) P += 1
256 #define STORE_PIXEL(DST, X, Y, VALUE) \
257 STORE_PIXEL_R3G3B2(DST, X, Y, VALUE)
258 #define FETCH_PIXEL(DST, SRC) \
259 FETCH_PIXEL_R3G3B2(DST, SRC)
261 #include "swrast_spantemp.h"
265 * Back-buffers are malloced memory and always private.
267 * BACK_PIXMAP (not supported)
271 swrast_set_span_funcs_back(struct swrast_renderbuffer *xrb,
274 switch (pixel_format) {
276 xrb->Base.GetRow = get_row_A8R8G8B8;
277 xrb->Base.GetValues = get_values_A8R8G8B8;
278 xrb->Base.PutRow = put_row_A8R8G8B8;
279 xrb->Base.PutRowRGB = put_row_rgb_A8R8G8B8;
280 xrb->Base.PutMonoRow = put_mono_row_A8R8G8B8;
281 xrb->Base.PutValues = put_values_A8R8G8B8;
282 xrb->Base.PutMonoValues = put_mono_values_A8R8G8B8;
285 xrb->Base.GetRow = get_row_X8R8G8B8;
286 xrb->Base.GetValues = get_values_X8R8G8B8;
287 xrb->Base.PutRow = put_row_X8R8G8B8;
288 xrb->Base.PutRowRGB = put_row_rgb_X8R8G8B8;
289 xrb->Base.PutMonoRow = put_mono_row_X8R8G8B8;
290 xrb->Base.PutValues = put_values_X8R8G8B8;
291 xrb->Base.PutMonoValues = put_mono_values_X8R8G8B8;
294 xrb->Base.GetRow = get_row_R5G6B5;
295 xrb->Base.GetValues = get_values_R5G6B5;
296 xrb->Base.PutRow = put_row_R5G6B5;
297 xrb->Base.PutRowRGB = put_row_rgb_R5G6B5;
298 xrb->Base.PutMonoRow = put_mono_row_R5G6B5;
299 xrb->Base.PutValues = put_values_R5G6B5;
300 xrb->Base.PutMonoValues = put_mono_values_R5G6B5;
303 xrb->Base.GetRow = get_row_R3G3B2;
304 xrb->Base.GetValues = get_values_R3G3B2;
305 xrb->Base.PutRow = put_row_R3G3B2;
306 xrb->Base.PutRowRGB = put_row_rgb_R3G3B2;
307 xrb->Base.PutMonoRow = put_mono_row_R3G3B2;
308 xrb->Base.PutValues = put_values_R3G3B2;
309 xrb->Base.PutMonoValues = put_mono_values_R3G3B2;
319 * Front-buffers are provided by the loader, the xorg loader uses pixmaps.
321 * WINDOW, An X window
322 * GLXWINDOW, GLX window
324 * PBUFFER GLX Pbuffer
327 swrast_set_span_funcs_front(struct swrast_renderbuffer *xrb,
330 switch (pixel_format) {
332 xrb->Base.GetRow = get_row_A8R8G8B8_front;
333 xrb->Base.GetValues = get_values_A8R8G8B8_front;
334 xrb->Base.PutRow = put_row_A8R8G8B8_front;
335 xrb->Base.PutRowRGB = put_row_rgb_A8R8G8B8_front;
336 xrb->Base.PutMonoRow = put_mono_row_A8R8G8B8_front;
337 xrb->Base.PutValues = put_values_A8R8G8B8_front;
338 xrb->Base.PutMonoValues = put_mono_values_A8R8G8B8_front;
341 xrb->Base.GetRow = get_row_X8R8G8B8_front;
342 xrb->Base.GetValues = get_values_X8R8G8B8_front;
343 xrb->Base.PutRow = put_row_X8R8G8B8_front;
344 xrb->Base.PutRowRGB = put_row_rgb_X8R8G8B8_front;
345 xrb->Base.PutMonoRow = put_mono_row_X8R8G8B8_front;
346 xrb->Base.PutValues = put_values_X8R8G8B8_front;
347 xrb->Base.PutMonoValues = put_mono_values_X8R8G8B8_front;
350 xrb->Base.GetRow = get_row_R5G6B5_front;
351 xrb->Base.GetValues = get_values_R5G6B5_front;
352 xrb->Base.PutRow = put_row_R5G6B5_front;
353 xrb->Base.PutRowRGB = put_row_rgb_R5G6B5_front;
354 xrb->Base.PutMonoRow = put_mono_row_R5G6B5_front;
355 xrb->Base.PutValues = put_values_R5G6B5_front;
356 xrb->Base.PutMonoValues = put_mono_values_R5G6B5_front;
359 xrb->Base.GetRow = get_row_R3G3B2_front;
360 xrb->Base.GetValues = get_values_R3G3B2_front;
361 xrb->Base.PutRow = put_row_R3G3B2_front;
362 xrb->Base.PutRowRGB = put_row_rgb_R3G3B2_front;
363 xrb->Base.PutMonoRow = put_mono_row_R3G3B2_front;
364 xrb->Base.PutValues = put_values_R3G3B2_front;
365 xrb->Base.PutMonoValues = put_mono_values_R3G3B2_front;