Merge branch 'mesa_7_6_branch' of git+ssh://agd5f@git.freedesktop.org/git/mesa/mesa
[mesa.git] / src / mesa / drivers / osmesa / osmesa.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
4 *
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 /*
27 * Off-Screen Mesa rendering / Rendering into client memory space
28 *
29 * Note on thread safety: this driver is thread safe. All
30 * functions are reentrant. The notion of current context is
31 * managed by the core _mesa_make_current() and _mesa_get_current_context()
32 * functions. Those functions are thread-safe.
33 */
34
35
36 #include "main/glheader.h"
37 #include "GL/osmesa.h"
38 #include "main/context.h"
39 #include "main/extensions.h"
40 #include "main/framebuffer.h"
41 #include "main/imports.h"
42 #include "main/mtypes.h"
43 #include "main/renderbuffer.h"
44 #include "swrast/swrast.h"
45 #include "swrast_setup/swrast_setup.h"
46 #include "swrast/s_context.h"
47 #include "swrast/s_lines.h"
48 #include "swrast/s_triangle.h"
49 #include "tnl/tnl.h"
50 #include "tnl/t_context.h"
51 #include "tnl/t_pipeline.h"
52 #include "drivers/common/driverfuncs.h"
53 #include "drivers/common/meta.h"
54 #include "vbo/vbo.h"
55
56
57
58 /**
59 * OSMesa rendering context, derived from core Mesa GLcontext.
60 */
61 struct osmesa_context
62 {
63 GLcontext mesa; /*< Base class - this must be first */
64 GLvisual *gl_visual; /*< Describes the buffers */
65 struct gl_renderbuffer *rb; /*< The user's colorbuffer */
66 GLframebuffer *gl_buffer; /*< The framebuffer, containing user's rb */
67 GLenum format; /*< User-specified context format */
68 GLint userRowLength; /*< user-specified number of pixels per row */
69 GLint rInd, gInd, bInd, aInd;/*< index offsets for RGBA formats */
70 GLvoid *rowaddr[MAX_HEIGHT]; /*< address of first pixel in each image row */
71 GLboolean yup; /*< TRUE -> Y increases upward */
72 /*< FALSE -> Y increases downward */
73 };
74
75
76 static INLINE OSMesaContext
77 OSMESA_CONTEXT(GLcontext *ctx)
78 {
79 /* Just cast, since we're using structure containment */
80 return (OSMesaContext) ctx;
81 }
82
83
84 /**********************************************************************/
85 /*** Private Device Driver Functions ***/
86 /**********************************************************************/
87
88
89 static const GLubyte *
90 get_string( GLcontext *ctx, GLenum name )
91 {
92 (void) ctx;
93 switch (name) {
94 case GL_RENDERER:
95 #if CHAN_BITS == 32
96 return (const GLubyte *) "Mesa OffScreen32";
97 #elif CHAN_BITS == 16
98 return (const GLubyte *) "Mesa OffScreen16";
99 #else
100 return (const GLubyte *) "Mesa OffScreen";
101 #endif
102 default:
103 return NULL;
104 }
105 }
106
107
108 static void
109 osmesa_update_state( GLcontext *ctx, GLuint new_state )
110 {
111 /* easy - just propogate */
112 _swrast_InvalidateState( ctx, new_state );
113 _swsetup_InvalidateState( ctx, new_state );
114 _tnl_InvalidateState( ctx, new_state );
115 _vbo_InvalidateState( ctx, new_state );
116 }
117
118
119
120 /**********************************************************************/
121 /***** Read/write spans/arrays of pixels *****/
122 /**********************************************************************/
123
124 /* 8-bit RGBA */
125 #define NAME(PREFIX) PREFIX##_RGBA8
126 #define RB_TYPE GLubyte
127 #define SPAN_VARS \
128 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
129 #define INIT_PIXEL_PTR(P, X, Y) \
130 GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
131 #define INC_PIXEL_PTR(P) P += 4
132 #define STORE_PIXEL(DST, X, Y, VALUE) \
133 DST[0] = VALUE[RCOMP]; \
134 DST[1] = VALUE[GCOMP]; \
135 DST[2] = VALUE[BCOMP]; \
136 DST[3] = VALUE[ACOMP]
137 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
138 DST[0] = VALUE[RCOMP]; \
139 DST[1] = VALUE[GCOMP]; \
140 DST[2] = VALUE[BCOMP]; \
141 DST[3] = 255
142 #define FETCH_PIXEL(DST, SRC) \
143 DST[RCOMP] = SRC[0]; \
144 DST[GCOMP] = SRC[1]; \
145 DST[BCOMP] = SRC[2]; \
146 DST[ACOMP] = SRC[3]
147 #include "swrast/s_spantemp.h"
148
149 /* 16-bit RGBA */
150 #define NAME(PREFIX) PREFIX##_RGBA16
151 #define RB_TYPE GLushort
152 #define SPAN_VARS \
153 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
154 #define INIT_PIXEL_PTR(P, X, Y) \
155 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
156 #define INC_PIXEL_PTR(P) P += 4
157 #define STORE_PIXEL(DST, X, Y, VALUE) \
158 DST[0] = VALUE[RCOMP]; \
159 DST[1] = VALUE[GCOMP]; \
160 DST[2] = VALUE[BCOMP]; \
161 DST[3] = VALUE[ACOMP]
162 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
163 DST[0] = VALUE[RCOMP]; \
164 DST[1] = VALUE[GCOMP]; \
165 DST[2] = VALUE[BCOMP]; \
166 DST[3] = 65535
167 #define FETCH_PIXEL(DST, SRC) \
168 DST[RCOMP] = SRC[0]; \
169 DST[GCOMP] = SRC[1]; \
170 DST[BCOMP] = SRC[2]; \
171 DST[ACOMP] = SRC[3]
172 #include "swrast/s_spantemp.h"
173
174 /* 32-bit RGBA */
175 #define NAME(PREFIX) PREFIX##_RGBA32
176 #define RB_TYPE GLfloat
177 #define SPAN_VARS \
178 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
179 #define INIT_PIXEL_PTR(P, X, Y) \
180 GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
181 #define INC_PIXEL_PTR(P) P += 4
182 #define STORE_PIXEL(DST, X, Y, VALUE) \
183 DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
184 DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
185 DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
186 DST[3] = CLAMP((VALUE[ACOMP]), 0.0F, 1.0F)
187 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
188 DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
189 DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
190 DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
191 DST[3] = 1.0F
192 #define FETCH_PIXEL(DST, SRC) \
193 DST[RCOMP] = SRC[0]; \
194 DST[GCOMP] = SRC[1]; \
195 DST[BCOMP] = SRC[2]; \
196 DST[ACOMP] = SRC[3]
197 #include "swrast/s_spantemp.h"
198
199
200 /* 8-bit BGRA */
201 #define NAME(PREFIX) PREFIX##_BGRA8
202 #define RB_TYPE GLubyte
203 #define SPAN_VARS \
204 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
205 #define INIT_PIXEL_PTR(P, X, Y) \
206 GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
207 #define INC_PIXEL_PTR(P) P += 4
208 #define STORE_PIXEL(DST, X, Y, VALUE) \
209 DST[2] = VALUE[RCOMP]; \
210 DST[1] = VALUE[GCOMP]; \
211 DST[0] = VALUE[BCOMP]; \
212 DST[3] = VALUE[ACOMP]
213 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
214 DST[2] = VALUE[RCOMP]; \
215 DST[1] = VALUE[GCOMP]; \
216 DST[0] = VALUE[BCOMP]; \
217 DST[3] = 255
218 #define FETCH_PIXEL(DST, SRC) \
219 DST[RCOMP] = SRC[2]; \
220 DST[GCOMP] = SRC[1]; \
221 DST[BCOMP] = SRC[0]; \
222 DST[ACOMP] = SRC[3]
223 #include "swrast/s_spantemp.h"
224
225 /* 16-bit BGRA */
226 #define NAME(PREFIX) PREFIX##_BGRA16
227 #define RB_TYPE GLushort
228 #define SPAN_VARS \
229 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
230 #define INIT_PIXEL_PTR(P, X, Y) \
231 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
232 #define INC_PIXEL_PTR(P) P += 4
233 #define STORE_PIXEL(DST, X, Y, VALUE) \
234 DST[2] = VALUE[RCOMP]; \
235 DST[1] = VALUE[GCOMP]; \
236 DST[0] = VALUE[BCOMP]; \
237 DST[3] = VALUE[ACOMP]
238 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
239 DST[2] = VALUE[RCOMP]; \
240 DST[1] = VALUE[GCOMP]; \
241 DST[0] = VALUE[BCOMP]; \
242 DST[3] = 65535
243 #define FETCH_PIXEL(DST, SRC) \
244 DST[RCOMP] = SRC[2]; \
245 DST[GCOMP] = SRC[1]; \
246 DST[BCOMP] = SRC[0]; \
247 DST[ACOMP] = SRC[3]
248 #include "swrast/s_spantemp.h"
249
250 /* 32-bit BGRA */
251 #define NAME(PREFIX) PREFIX##_BGRA32
252 #define RB_TYPE GLfloat
253 #define SPAN_VARS \
254 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
255 #define INIT_PIXEL_PTR(P, X, Y) \
256 GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
257 #define INC_PIXEL_PTR(P) P += 4
258 #define STORE_PIXEL(DST, X, Y, VALUE) \
259 DST[2] = VALUE[RCOMP]; \
260 DST[1] = VALUE[GCOMP]; \
261 DST[0] = VALUE[BCOMP]; \
262 DST[3] = VALUE[ACOMP]
263 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
264 DST[2] = VALUE[RCOMP]; \
265 DST[1] = VALUE[GCOMP]; \
266 DST[0] = VALUE[BCOMP]; \
267 DST[3] = 1.0F
268 #define FETCH_PIXEL(DST, SRC) \
269 DST[RCOMP] = SRC[2]; \
270 DST[GCOMP] = SRC[1]; \
271 DST[BCOMP] = SRC[0]; \
272 DST[ACOMP] = SRC[3]
273 #include "swrast/s_spantemp.h"
274
275
276 /* 8-bit ARGB */
277 #define NAME(PREFIX) PREFIX##_ARGB8
278 #define RB_TYPE GLubyte
279 #define SPAN_VARS \
280 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
281 #define INIT_PIXEL_PTR(P, X, Y) \
282 GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
283 #define INC_PIXEL_PTR(P) P += 4
284 #define STORE_PIXEL(DST, X, Y, VALUE) \
285 DST[1] = VALUE[RCOMP]; \
286 DST[2] = VALUE[GCOMP]; \
287 DST[3] = VALUE[BCOMP]; \
288 DST[0] = VALUE[ACOMP]
289 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
290 DST[1] = VALUE[RCOMP]; \
291 DST[2] = VALUE[GCOMP]; \
292 DST[3] = VALUE[BCOMP]; \
293 DST[0] = 255
294 #define FETCH_PIXEL(DST, SRC) \
295 DST[RCOMP] = SRC[1]; \
296 DST[GCOMP] = SRC[2]; \
297 DST[BCOMP] = SRC[3]; \
298 DST[ACOMP] = SRC[0]
299 #include "swrast/s_spantemp.h"
300
301 /* 16-bit ARGB */
302 #define NAME(PREFIX) PREFIX##_ARGB16
303 #define RB_TYPE GLushort
304 #define SPAN_VARS \
305 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
306 #define INIT_PIXEL_PTR(P, X, Y) \
307 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
308 #define INC_PIXEL_PTR(P) P += 4
309 #define STORE_PIXEL(DST, X, Y, VALUE) \
310 DST[1] = VALUE[RCOMP]; \
311 DST[2] = VALUE[GCOMP]; \
312 DST[3] = VALUE[BCOMP]; \
313 DST[0] = VALUE[ACOMP]
314 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
315 DST[1] = VALUE[RCOMP]; \
316 DST[2] = VALUE[GCOMP]; \
317 DST[3] = VALUE[BCOMP]; \
318 DST[0] = 65535
319 #define FETCH_PIXEL(DST, SRC) \
320 DST[RCOMP] = SRC[1]; \
321 DST[GCOMP] = SRC[2]; \
322 DST[BCOMP] = SRC[3]; \
323 DST[ACOMP] = SRC[0]
324 #include "swrast/s_spantemp.h"
325
326 /* 32-bit ARGB */
327 #define NAME(PREFIX) PREFIX##_ARGB32
328 #define RB_TYPE GLfloat
329 #define SPAN_VARS \
330 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
331 #define INIT_PIXEL_PTR(P, X, Y) \
332 GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
333 #define INC_PIXEL_PTR(P) P += 4
334 #define STORE_PIXEL(DST, X, Y, VALUE) \
335 DST[1] = VALUE[RCOMP]; \
336 DST[2] = VALUE[GCOMP]; \
337 DST[3] = VALUE[BCOMP]; \
338 DST[0] = VALUE[ACOMP]
339 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
340 DST[1] = VALUE[RCOMP]; \
341 DST[2] = VALUE[GCOMP]; \
342 DST[3] = VALUE[BCOMP]; \
343 DST[0] = 1.0F
344 #define FETCH_PIXEL(DST, SRC) \
345 DST[RCOMP] = SRC[1]; \
346 DST[GCOMP] = SRC[2]; \
347 DST[BCOMP] = SRC[3]; \
348 DST[ACOMP] = SRC[0]
349 #include "swrast/s_spantemp.h"
350
351
352 /* 8-bit RGB */
353 #define NAME(PREFIX) PREFIX##_RGB8
354 #define RB_TYPE GLubyte
355 #define SPAN_VARS \
356 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
357 #define INIT_PIXEL_PTR(P, X, Y) \
358 GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X)
359 #define INC_PIXEL_PTR(P) P += 3
360 #define STORE_PIXEL(DST, X, Y, VALUE) \
361 DST[0] = VALUE[RCOMP]; \
362 DST[1] = VALUE[GCOMP]; \
363 DST[2] = VALUE[BCOMP]
364 #define FETCH_PIXEL(DST, SRC) \
365 DST[RCOMP] = SRC[0]; \
366 DST[GCOMP] = SRC[1]; \
367 DST[BCOMP] = SRC[2]; \
368 DST[ACOMP] = 255
369 #include "swrast/s_spantemp.h"
370
371 /* 16-bit RGB */
372 #define NAME(PREFIX) PREFIX##_RGB16
373 #define RB_TYPE GLushort
374 #define SPAN_VARS \
375 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
376 #define INIT_PIXEL_PTR(P, X, Y) \
377 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X)
378 #define INC_PIXEL_PTR(P) P += 3
379 #define STORE_PIXEL(DST, X, Y, VALUE) \
380 DST[0] = VALUE[RCOMP]; \
381 DST[1] = VALUE[GCOMP]; \
382 DST[2] = VALUE[BCOMP]
383 #define FETCH_PIXEL(DST, SRC) \
384 DST[RCOMP] = SRC[0]; \
385 DST[GCOMP] = SRC[1]; \
386 DST[BCOMP] = SRC[2]; \
387 DST[ACOMP] = 65535U
388 #include "swrast/s_spantemp.h"
389
390 /* 32-bit RGB */
391 #define NAME(PREFIX) PREFIX##_RGB32
392 #define RB_TYPE GLfloat
393 #define SPAN_VARS \
394 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
395 #define INIT_PIXEL_PTR(P, X, Y) \
396 GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X)
397 #define INC_PIXEL_PTR(P) P += 3
398 #define STORE_PIXEL(DST, X, Y, VALUE) \
399 DST[0] = VALUE[RCOMP]; \
400 DST[1] = VALUE[GCOMP]; \
401 DST[2] = VALUE[BCOMP]
402 #define FETCH_PIXEL(DST, SRC) \
403 DST[RCOMP] = SRC[0]; \
404 DST[GCOMP] = SRC[1]; \
405 DST[BCOMP] = SRC[2]; \
406 DST[ACOMP] = 1.0F
407 #include "swrast/s_spantemp.h"
408
409
410 /* 8-bit BGR */
411 #define NAME(PREFIX) PREFIX##_BGR8
412 #define RB_TYPE GLubyte
413 #define SPAN_VARS \
414 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
415 #define INIT_PIXEL_PTR(P, X, Y) \
416 GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X)
417 #define INC_PIXEL_PTR(P) P += 3
418 #define STORE_PIXEL(DST, X, Y, VALUE) \
419 DST[2] = VALUE[RCOMP]; \
420 DST[1] = VALUE[GCOMP]; \
421 DST[0] = VALUE[BCOMP]
422 #define FETCH_PIXEL(DST, SRC) \
423 DST[RCOMP] = SRC[2]; \
424 DST[GCOMP] = SRC[1]; \
425 DST[BCOMP] = SRC[0]; \
426 DST[ACOMP] = 255
427 #include "swrast/s_spantemp.h"
428
429 /* 16-bit BGR */
430 #define NAME(PREFIX) PREFIX##_BGR16
431 #define RB_TYPE GLushort
432 #define SPAN_VARS \
433 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
434 #define INIT_PIXEL_PTR(P, X, Y) \
435 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X)
436 #define INC_PIXEL_PTR(P) P += 3
437 #define STORE_PIXEL(DST, X, Y, VALUE) \
438 DST[2] = VALUE[RCOMP]; \
439 DST[1] = VALUE[GCOMP]; \
440 DST[0] = VALUE[BCOMP]
441 #define FETCH_PIXEL(DST, SRC) \
442 DST[RCOMP] = SRC[2]; \
443 DST[GCOMP] = SRC[1]; \
444 DST[BCOMP] = SRC[0]; \
445 DST[ACOMP] = 65535
446 #include "swrast/s_spantemp.h"
447
448 /* 32-bit BGR */
449 #define NAME(PREFIX) PREFIX##_BGR32
450 #define RB_TYPE GLfloat
451 #define SPAN_VARS \
452 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
453 #define INIT_PIXEL_PTR(P, X, Y) \
454 GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X)
455 #define INC_PIXEL_PTR(P) P += 3
456 #define STORE_PIXEL(DST, X, Y, VALUE) \
457 DST[2] = VALUE[RCOMP]; \
458 DST[1] = VALUE[GCOMP]; \
459 DST[0] = VALUE[BCOMP]
460 #define FETCH_PIXEL(DST, SRC) \
461 DST[RCOMP] = SRC[2]; \
462 DST[GCOMP] = SRC[1]; \
463 DST[BCOMP] = SRC[0]; \
464 DST[ACOMP] = 1.0F
465 #include "swrast/s_spantemp.h"
466
467
468 /* 16-bit 5/6/5 RGB */
469 #define NAME(PREFIX) PREFIX##_RGB_565
470 #define RB_TYPE GLubyte
471 #define SPAN_VARS \
472 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
473 #define INIT_PIXEL_PTR(P, X, Y) \
474 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X)
475 #define INC_PIXEL_PTR(P) P += 1
476 #define STORE_PIXEL(DST, X, Y, VALUE) \
477 *DST = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) )
478 #define FETCH_PIXEL(DST, SRC) \
479 DST[RCOMP] = ( (((*SRC) >> 8) & 0xf8) | (((*SRC) >> 11) & 0x7) ); \
480 DST[GCOMP] = ( (((*SRC) >> 3) & 0xfc) | (((*SRC) >> 5) & 0x3) ); \
481 DST[BCOMP] = ( (((*SRC) << 3) & 0xf8) | (((*SRC) ) & 0x7) ); \
482 DST[ACOMP] = CHAN_MAX
483 #include "swrast/s_spantemp.h"
484
485
486 /* color index */
487 #define NAME(PREFIX) PREFIX##_CI
488 #define CI_MODE
489 #define RB_TYPE GLubyte
490 #define SPAN_VARS \
491 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
492 #define INIT_PIXEL_PTR(P, X, Y) \
493 GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + (X)
494 #define INC_PIXEL_PTR(P) P += 1
495 #define STORE_PIXEL(DST, X, Y, VALUE) \
496 *DST = VALUE[0]
497 #define FETCH_PIXEL(DST, SRC) \
498 DST = SRC[0]
499 #include "swrast/s_spantemp.h"
500
501
502
503
504 /**
505 * Macros for optimized line/triangle rendering.
506 * Only for 8-bit channel, RGBA, BGRA, ARGB formats.
507 */
508
509 #define PACK_RGBA(DST, R, G, B, A) \
510 do { \
511 (DST)[osmesa->rInd] = R; \
512 (DST)[osmesa->gInd] = G; \
513 (DST)[osmesa->bInd] = B; \
514 (DST)[osmesa->aInd] = A; \
515 } while (0)
516
517 #define PIXELADDR4(X,Y) ((GLchan *) osmesa->rowaddr[Y] + 4 * (X))
518
519
520 /**
521 * Draw a flat-shaded, RGB line into an osmesa buffer.
522 */
523 #define NAME flat_rgba_line
524 #define CLIP_HACK 1
525 #define SETUP_CODE \
526 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
527 const GLchan *color = vert1->color;
528
529 #define PLOT(X, Y) \
530 do { \
531 GLchan *p = PIXELADDR4(X, Y); \
532 PACK_RGBA(p, color[0], color[1], color[2], color[3]); \
533 } while (0)
534
535 #ifdef WIN32
536 #include "..\swrast\s_linetemp.h"
537 #else
538 #include "swrast/s_linetemp.h"
539 #endif
540
541
542
543 /**
544 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
545 */
546 #define NAME flat_rgba_z_line
547 #define CLIP_HACK 1
548 #define INTERP_Z 1
549 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
550 #define SETUP_CODE \
551 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
552 const GLchan *color = vert1->color;
553
554 #define PLOT(X, Y) \
555 do { \
556 if (Z < *zPtr) { \
557 GLchan *p = PIXELADDR4(X, Y); \
558 PACK_RGBA(p, color[RCOMP], color[GCOMP], \
559 color[BCOMP], color[ACOMP]); \
560 *zPtr = Z; \
561 } \
562 } while (0)
563
564 #ifdef WIN32
565 #include "..\swrast\s_linetemp.h"
566 #else
567 #include "swrast/s_linetemp.h"
568 #endif
569
570
571
572 /**
573 * Analyze context state to see if we can provide a fast line drawing
574 * function. Otherwise, return NULL.
575 */
576 static swrast_line_func
577 osmesa_choose_line_function( GLcontext *ctx )
578 {
579 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
580 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
581
582 if (osmesa->rb->DataType != GL_UNSIGNED_BYTE)
583 return NULL;
584
585 if (ctx->RenderMode != GL_RENDER) return NULL;
586 if (ctx->Line.SmoothFlag) return NULL;
587 if (ctx->Texture._EnabledUnits) return NULL;
588 if (ctx->Light.ShadeModel != GL_FLAT) return NULL;
589 if (ctx->Line.Width != 1.0F) return NULL;
590 if (ctx->Line.StippleFlag) return NULL;
591 if (ctx->Line.SmoothFlag) return NULL;
592 if (osmesa->format != OSMESA_RGBA &&
593 osmesa->format != OSMESA_BGRA &&
594 osmesa->format != OSMESA_ARGB) return NULL;
595
596 if (swrast->_RasterMask==DEPTH_BIT
597 && ctx->Depth.Func==GL_LESS
598 && ctx->Depth.Mask==GL_TRUE
599 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
600 return (swrast_line_func) flat_rgba_z_line;
601 }
602
603 if (swrast->_RasterMask == 0) {
604 return (swrast_line_func) flat_rgba_line;
605 }
606
607 return (swrast_line_func) NULL;
608 }
609
610
611 /**********************************************************************/
612 /***** Optimized triangle rendering *****/
613 /**********************************************************************/
614
615
616 /*
617 * Smooth-shaded, z-less triangle, RGBA color.
618 */
619 #define NAME smooth_rgba_z_triangle
620 #define INTERP_Z 1
621 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
622 #define INTERP_RGB 1
623 #define INTERP_ALPHA 1
624 #define SETUP_CODE \
625 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
626 #define RENDER_SPAN( span ) { \
627 GLuint i; \
628 GLchan *img = PIXELADDR4(span.x, span.y); \
629 for (i = 0; i < span.end; i++, img += 4) { \
630 const GLuint z = FixedToDepth(span.z); \
631 if (z < zRow[i]) { \
632 PACK_RGBA(img, FixedToChan(span.red), \
633 FixedToChan(span.green), FixedToChan(span.blue), \
634 FixedToChan(span.alpha)); \
635 zRow[i] = z; \
636 } \
637 span.red += span.redStep; \
638 span.green += span.greenStep; \
639 span.blue += span.blueStep; \
640 span.alpha += span.alphaStep; \
641 span.z += span.zStep; \
642 } \
643 }
644 #ifdef WIN32
645 #include "..\swrast\s_tritemp.h"
646 #else
647 #include "swrast/s_tritemp.h"
648 #endif
649
650
651
652 /*
653 * Flat-shaded, z-less triangle, RGBA color.
654 */
655 #define NAME flat_rgba_z_triangle
656 #define INTERP_Z 1
657 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
658 #define SETUP_CODE \
659 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
660 GLuint pixel; \
661 PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1], \
662 v2->color[2], v2->color[3]);
663
664 #define RENDER_SPAN( span ) { \
665 GLuint i; \
666 GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \
667 for (i = 0; i < span.end; i++) { \
668 const GLuint z = FixedToDepth(span.z); \
669 if (z < zRow[i]) { \
670 img[i] = pixel; \
671 zRow[i] = z; \
672 } \
673 span.z += span.zStep; \
674 } \
675 }
676 #ifdef WIN32
677 #include "..\swrast\s_tritemp.h"
678 #else
679 #include "swrast/s_tritemp.h"
680 #endif
681
682
683
684 /**
685 * Return pointer to an optimized triangle function if possible.
686 */
687 static swrast_tri_func
688 osmesa_choose_triangle_function( GLcontext *ctx )
689 {
690 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
691 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
692
693 if (osmesa->rb->DataType != GL_UNSIGNED_BYTE)
694 return (swrast_tri_func) NULL;
695
696 if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL;
697 if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL;
698 if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL;
699 if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL;
700 if (osmesa->format != OSMESA_RGBA &&
701 osmesa->format != OSMESA_BGRA &&
702 osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL;
703 if (ctx->Polygon.CullFlag &&
704 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
705 return (swrast_tri_func) NULL;
706
707 if (swrast->_RasterMask == DEPTH_BIT &&
708 ctx->Depth.Func == GL_LESS &&
709 ctx->Depth.Mask == GL_TRUE &&
710 ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
711 if (ctx->Light.ShadeModel == GL_SMOOTH) {
712 return (swrast_tri_func) smooth_rgba_z_triangle;
713 }
714 else {
715 return (swrast_tri_func) flat_rgba_z_triangle;
716 }
717 }
718 return (swrast_tri_func) NULL;
719 }
720
721
722
723 /* Override for the swrast triangle-selection function. Try to use one
724 * of our internal triangle functions, otherwise fall back to the
725 * standard swrast functions.
726 */
727 static void
728 osmesa_choose_triangle( GLcontext *ctx )
729 {
730 SWcontext *swrast = SWRAST_CONTEXT(ctx);
731
732 swrast->Triangle = osmesa_choose_triangle_function( ctx );
733 if (!swrast->Triangle)
734 _swrast_choose_triangle( ctx );
735 }
736
737 static void
738 osmesa_choose_line( GLcontext *ctx )
739 {
740 SWcontext *swrast = SWRAST_CONTEXT(ctx);
741
742 swrast->Line = osmesa_choose_line_function( ctx );
743 if (!swrast->Line)
744 _swrast_choose_line( ctx );
745 }
746
747
748
749 /**
750 * Recompute the values of the context's rowaddr array.
751 */
752 static void
753 compute_row_addresses( OSMesaContext osmesa )
754 {
755 GLint bytesPerPixel, bytesPerRow, i;
756 GLubyte *origin = (GLubyte *) osmesa->rb->Data;
757 GLint bpc; /* bytes per channel */
758 GLint rowlength; /* in pixels */
759 GLint height = osmesa->rb->Height;
760
761 if (osmesa->userRowLength)
762 rowlength = osmesa->userRowLength;
763 else
764 rowlength = osmesa->rb->Width;
765
766 if (osmesa->rb->DataType == GL_UNSIGNED_BYTE)
767 bpc = 1;
768 else if (osmesa->rb->DataType == GL_UNSIGNED_SHORT)
769 bpc = 2;
770 else if (osmesa->rb->DataType == GL_FLOAT)
771 bpc = 4;
772 else {
773 _mesa_problem(&osmesa->mesa,
774 "Unexpected datatype in osmesa::compute_row_addresses");
775 return;
776 }
777
778 if (osmesa->format == OSMESA_COLOR_INDEX) {
779 /* CI mode */
780 bytesPerPixel = 1 * sizeof(GLubyte);
781 }
782 else if ((osmesa->format == OSMESA_RGB) || (osmesa->format == OSMESA_BGR)) {
783 /* RGB mode */
784 bytesPerPixel = 3 * bpc;
785 }
786 else if (osmesa->format == OSMESA_RGB_565) {
787 /* 5/6/5 RGB pixel in 16 bits */
788 bytesPerPixel = 2;
789 }
790 else {
791 /* RGBA mode */
792 bytesPerPixel = 4 * bpc;
793 }
794
795 bytesPerRow = rowlength * bytesPerPixel;
796
797 if (osmesa->yup) {
798 /* Y=0 is bottom line of window */
799 for (i = 0; i < height; i++) {
800 osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + i * bytesPerRow);
801 }
802 }
803 else {
804 /* Y=0 is top line of window */
805 for (i = 0; i < height; i++) {
806 GLint j = height - i - 1;
807 osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + j * bytesPerRow);
808 }
809 }
810 }
811
812
813
814 /**
815 * Don't use _mesa_delete_renderbuffer since we can't free rb->Data.
816 */
817 static void
818 osmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
819 {
820 _mesa_free(rb);
821 }
822
823
824 /**
825 * Allocate renderbuffer storage. We don't actually allocate any storage
826 * since we're using a user-provided buffer.
827 * Just set up all the gl_renderbuffer methods.
828 */
829 static GLboolean
830 osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
831 GLenum internalFormat, GLuint width, GLuint height)
832 {
833 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
834 GLint bpc; /* bits per channel */
835
836 if (rb->DataType == GL_UNSIGNED_BYTE)
837 bpc = 8;
838 else if (rb->DataType == GL_UNSIGNED_SHORT)
839 bpc = 16;
840 else
841 bpc = 32;
842
843 rb->RedBits =
844 rb->GreenBits =
845 rb->BlueBits =
846 rb->AlphaBits = bpc;
847
848 /* Note: we can ignoring internalFormat for "window-system" renderbuffers */
849 (void) internalFormat;
850
851 if (osmesa->format == OSMESA_RGBA) {
852 if (rb->DataType == GL_UNSIGNED_BYTE) {
853 rb->GetRow = get_row_RGBA8;
854 rb->GetValues = get_values_RGBA8;
855 rb->PutRow = put_row_RGBA8;
856 rb->PutRowRGB = put_row_rgb_RGBA8;
857 rb->PutMonoRow = put_mono_row_RGBA8;
858 rb->PutValues = put_values_RGBA8;
859 rb->PutMonoValues = put_mono_values_RGBA8;
860 }
861 else if (rb->DataType == GL_UNSIGNED_SHORT) {
862 rb->GetRow = get_row_RGBA16;
863 rb->GetValues = get_values_RGBA16;
864 rb->PutRow = put_row_RGBA16;
865 rb->PutRowRGB = put_row_rgb_RGBA16;
866 rb->PutMonoRow = put_mono_row_RGBA16;
867 rb->PutValues = put_values_RGBA16;
868 rb->PutMonoValues = put_mono_values_RGBA16;
869 }
870 else {
871 rb->GetRow = get_row_RGBA32;
872 rb->GetValues = get_values_RGBA32;
873 rb->PutRow = put_row_RGBA32;
874 rb->PutRowRGB = put_row_rgb_RGBA32;
875 rb->PutMonoRow = put_mono_row_RGBA32;
876 rb->PutValues = put_values_RGBA32;
877 rb->PutMonoValues = put_mono_values_RGBA32;
878 }
879 rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
880 }
881 else if (osmesa->format == OSMESA_BGRA) {
882 if (rb->DataType == GL_UNSIGNED_BYTE) {
883 rb->GetRow = get_row_BGRA8;
884 rb->GetValues = get_values_BGRA8;
885 rb->PutRow = put_row_BGRA8;
886 rb->PutRowRGB = put_row_rgb_BGRA8;
887 rb->PutMonoRow = put_mono_row_BGRA8;
888 rb->PutValues = put_values_BGRA8;
889 rb->PutMonoValues = put_mono_values_BGRA8;
890 }
891 else if (rb->DataType == GL_UNSIGNED_SHORT) {
892 rb->GetRow = get_row_BGRA16;
893 rb->GetValues = get_values_BGRA16;
894 rb->PutRow = put_row_BGRA16;
895 rb->PutRowRGB = put_row_rgb_BGRA16;
896 rb->PutMonoRow = put_mono_row_BGRA16;
897 rb->PutValues = put_values_BGRA16;
898 rb->PutMonoValues = put_mono_values_BGRA16;
899 }
900 else {
901 rb->GetRow = get_row_BGRA32;
902 rb->GetValues = get_values_BGRA32;
903 rb->PutRow = put_row_BGRA32;
904 rb->PutRowRGB = put_row_rgb_BGRA32;
905 rb->PutMonoRow = put_mono_row_BGRA32;
906 rb->PutValues = put_values_BGRA32;
907 rb->PutMonoValues = put_mono_values_BGRA32;
908 }
909 rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
910 }
911 else if (osmesa->format == OSMESA_ARGB) {
912 if (rb->DataType == GL_UNSIGNED_BYTE) {
913 rb->GetRow = get_row_ARGB8;
914 rb->GetValues = get_values_ARGB8;
915 rb->PutRow = put_row_ARGB8;
916 rb->PutRowRGB = put_row_rgb_ARGB8;
917 rb->PutMonoRow = put_mono_row_ARGB8;
918 rb->PutValues = put_values_ARGB8;
919 rb->PutMonoValues = put_mono_values_ARGB8;
920 }
921 else if (rb->DataType == GL_UNSIGNED_SHORT) {
922 rb->GetRow = get_row_ARGB16;
923 rb->GetValues = get_values_ARGB16;
924 rb->PutRow = put_row_ARGB16;
925 rb->PutRowRGB = put_row_rgb_ARGB16;
926 rb->PutMonoRow = put_mono_row_ARGB16;
927 rb->PutValues = put_values_ARGB16;
928 rb->PutMonoValues = put_mono_values_ARGB16;
929 }
930 else {
931 rb->GetRow = get_row_ARGB32;
932 rb->GetValues = get_values_ARGB32;
933 rb->PutRow = put_row_ARGB32;
934 rb->PutRowRGB = put_row_rgb_ARGB32;
935 rb->PutMonoRow = put_mono_row_ARGB32;
936 rb->PutValues = put_values_ARGB32;
937 rb->PutMonoValues = put_mono_values_ARGB32;
938 }
939 rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
940 }
941 else if (osmesa->format == OSMESA_RGB) {
942 if (rb->DataType == GL_UNSIGNED_BYTE) {
943 rb->GetRow = get_row_RGB8;
944 rb->GetValues = get_values_RGB8;
945 rb->PutRow = put_row_RGB8;
946 rb->PutRowRGB = put_row_rgb_RGB8;
947 rb->PutMonoRow = put_mono_row_RGB8;
948 rb->PutValues = put_values_RGB8;
949 rb->PutMonoValues = put_mono_values_RGB8;
950 }
951 else if (rb->DataType == GL_UNSIGNED_SHORT) {
952 rb->GetRow = get_row_RGB16;
953 rb->GetValues = get_values_RGB16;
954 rb->PutRow = put_row_RGB16;
955 rb->PutRowRGB = put_row_rgb_RGB16;
956 rb->PutMonoRow = put_mono_row_RGB16;
957 rb->PutValues = put_values_RGB16;
958 rb->PutMonoValues = put_mono_values_RGB16;
959 }
960 else {
961 rb->GetRow = get_row_RGB32;
962 rb->GetValues = get_values_RGB32;
963 rb->PutRow = put_row_RGB32;
964 rb->PutRowRGB = put_row_rgb_RGB32;
965 rb->PutMonoRow = put_mono_row_RGB32;
966 rb->PutValues = put_values_RGB32;
967 rb->PutMonoValues = put_mono_values_RGB32;
968 }
969 rb->RedBits = rb->GreenBits = rb->BlueBits = bpc;
970 }
971 else if (osmesa->format == OSMESA_BGR) {
972 if (rb->DataType == GL_UNSIGNED_BYTE) {
973 rb->GetRow = get_row_BGR8;
974 rb->GetValues = get_values_BGR8;
975 rb->PutRow = put_row_BGR8;
976 rb->PutRowRGB = put_row_rgb_BGR8;
977 rb->PutMonoRow = put_mono_row_BGR8;
978 rb->PutValues = put_values_BGR8;
979 rb->PutMonoValues = put_mono_values_BGR8;
980 }
981 else if (rb->DataType == GL_UNSIGNED_SHORT) {
982 rb->GetRow = get_row_BGR16;
983 rb->GetValues = get_values_BGR16;
984 rb->PutRow = put_row_BGR16;
985 rb->PutRowRGB = put_row_rgb_BGR16;
986 rb->PutMonoRow = put_mono_row_BGR16;
987 rb->PutValues = put_values_BGR16;
988 rb->PutMonoValues = put_mono_values_BGR16;
989 }
990 else {
991 rb->GetRow = get_row_BGR32;
992 rb->GetValues = get_values_BGR32;
993 rb->PutRow = put_row_BGR32;
994 rb->PutRowRGB = put_row_rgb_BGR32;
995 rb->PutMonoRow = put_mono_row_BGR32;
996 rb->PutValues = put_values_BGR32;
997 rb->PutMonoValues = put_mono_values_BGR32;
998 }
999 rb->RedBits = rb->GreenBits = rb->BlueBits = bpc;
1000 }
1001 else if (osmesa->format == OSMESA_RGB_565) {
1002 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
1003 rb->GetRow = get_row_RGB_565;
1004 rb->GetValues = get_values_RGB_565;
1005 rb->PutRow = put_row_RGB_565;
1006 rb->PutRowRGB = put_row_rgb_RGB_565;
1007 rb->PutMonoRow = put_mono_row_RGB_565;
1008 rb->PutValues = put_values_RGB_565;
1009 rb->PutMonoValues = put_mono_values_RGB_565;
1010 rb->RedBits = 5;
1011 rb->GreenBits = 6;
1012 rb->BlueBits = 5;
1013 }
1014 else if (osmesa->format == OSMESA_COLOR_INDEX) {
1015 rb->GetRow = get_row_CI;
1016 rb->GetValues = get_values_CI;
1017 rb->PutRow = put_row_CI;
1018 rb->PutMonoRow = put_mono_row_CI;
1019 rb->PutValues = put_values_CI;
1020 rb->PutMonoValues = put_mono_values_CI;
1021 rb->IndexBits = 8;
1022 }
1023 else {
1024 _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage");
1025 }
1026
1027 rb->Width = width;
1028 rb->Height = height;
1029
1030 compute_row_addresses( osmesa );
1031
1032 return GL_TRUE;
1033 }
1034
1035
1036 /**
1037 * Allocate a new renderbuffer to describe the user-provided color buffer.
1038 */
1039 static struct gl_renderbuffer *
1040 new_osmesa_renderbuffer(GLcontext *ctx, GLenum format, GLenum type)
1041 {
1042 const GLuint name = 0;
1043 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1044 if (rb) {
1045 rb->RefCount = 1;
1046 rb->Delete = osmesa_delete_renderbuffer;
1047 rb->AllocStorage = osmesa_renderbuffer_storage;
1048
1049 if (format == OSMESA_COLOR_INDEX) {
1050 rb->InternalFormat = GL_COLOR_INDEX;
1051 rb->_ActualFormat = GL_COLOR_INDEX8_EXT;
1052 rb->_BaseFormat = GL_COLOR_INDEX;
1053 rb->DataType = GL_UNSIGNED_BYTE;
1054 }
1055 else {
1056 rb->InternalFormat = GL_RGBA;
1057 rb->_ActualFormat = GL_RGBA;
1058 rb->_BaseFormat = GL_RGBA;
1059 rb->DataType = type;
1060 }
1061 }
1062 return rb;
1063 }
1064
1065
1066 /**********************************************************************/
1067 /***** Public Functions *****/
1068 /**********************************************************************/
1069
1070
1071 /**
1072 * Create an Off-Screen Mesa rendering context. The only attribute needed is
1073 * an RGBA vs Color-Index mode flag.
1074 *
1075 * Input: format - either GL_RGBA or GL_COLOR_INDEX
1076 * sharelist - specifies another OSMesaContext with which to share
1077 * display lists. NULL indicates no sharing.
1078 * Return: an OSMesaContext or 0 if error
1079 */
1080 GLAPI OSMesaContext GLAPIENTRY
1081 OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
1082 {
1083 const GLint accumBits = (format == OSMESA_COLOR_INDEX) ? 0 : 16;
1084 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
1085 8, accumBits, sharelist);
1086 }
1087
1088
1089
1090 /**
1091 * New in Mesa 3.5
1092 *
1093 * Create context and specify size of ancillary buffers.
1094 */
1095 GLAPI OSMesaContext GLAPIENTRY
1096 OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
1097 GLint accumBits, OSMesaContext sharelist )
1098 {
1099 OSMesaContext osmesa;
1100 struct dd_function_table functions;
1101 GLint rind, gind, bind, aind;
1102 GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
1103 GLboolean rgbmode;
1104 GLenum type = CHAN_TYPE;
1105
1106 rind = gind = bind = aind = 0;
1107 if (format==OSMESA_COLOR_INDEX) {
1108 indexBits = 8;
1109 rgbmode = GL_FALSE;
1110 }
1111 else if (format==OSMESA_RGBA) {
1112 indexBits = 0;
1113 redBits = CHAN_BITS;
1114 greenBits = CHAN_BITS;
1115 blueBits = CHAN_BITS;
1116 alphaBits = CHAN_BITS;
1117 rind = 0;
1118 gind = 1;
1119 bind = 2;
1120 aind = 3;
1121 rgbmode = GL_TRUE;
1122 }
1123 else if (format==OSMESA_BGRA) {
1124 indexBits = 0;
1125 redBits = CHAN_BITS;
1126 greenBits = CHAN_BITS;
1127 blueBits = CHAN_BITS;
1128 alphaBits = CHAN_BITS;
1129 bind = 0;
1130 gind = 1;
1131 rind = 2;
1132 aind = 3;
1133 rgbmode = GL_TRUE;
1134 }
1135 else if (format==OSMESA_ARGB) {
1136 indexBits = 0;
1137 redBits = CHAN_BITS;
1138 greenBits = CHAN_BITS;
1139 blueBits = CHAN_BITS;
1140 alphaBits = CHAN_BITS;
1141 aind = 0;
1142 rind = 1;
1143 gind = 2;
1144 bind = 3;
1145 rgbmode = GL_TRUE;
1146 }
1147 else if (format==OSMESA_RGB) {
1148 indexBits = 0;
1149 redBits = CHAN_BITS;
1150 greenBits = CHAN_BITS;
1151 blueBits = CHAN_BITS;
1152 alphaBits = 0;
1153 rind = 0;
1154 gind = 1;
1155 bind = 2;
1156 rgbmode = GL_TRUE;
1157 }
1158 else if (format==OSMESA_BGR) {
1159 indexBits = 0;
1160 redBits = CHAN_BITS;
1161 greenBits = CHAN_BITS;
1162 blueBits = CHAN_BITS;
1163 alphaBits = 0;
1164 rind = 2;
1165 gind = 1;
1166 bind = 0;
1167 rgbmode = GL_TRUE;
1168 }
1169 #if CHAN_TYPE == GL_UNSIGNED_BYTE
1170 else if (format==OSMESA_RGB_565) {
1171 indexBits = 0;
1172 redBits = 5;
1173 greenBits = 6;
1174 blueBits = 5;
1175 alphaBits = 0;
1176 rind = 0; /* not used */
1177 gind = 0;
1178 bind = 0;
1179 rgbmode = GL_TRUE;
1180 }
1181 #endif
1182 else {
1183 return NULL;
1184 }
1185
1186 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
1187 if (osmesa) {
1188 osmesa->gl_visual = _mesa_create_visual( rgbmode,
1189 GL_FALSE, /* double buffer */
1190 GL_FALSE, /* stereo */
1191 redBits,
1192 greenBits,
1193 blueBits,
1194 alphaBits,
1195 indexBits,
1196 depthBits,
1197 stencilBits,
1198 accumBits,
1199 accumBits,
1200 accumBits,
1201 alphaBits ? accumBits : 0,
1202 1 /* num samples */
1203 );
1204 if (!osmesa->gl_visual) {
1205 _mesa_free(osmesa);
1206 return NULL;
1207 }
1208
1209 /* Initialize device driver function table */
1210 _mesa_init_driver_functions(&functions);
1211 /* override with our functions */
1212 functions.GetString = get_string;
1213 functions.UpdateState = osmesa_update_state;
1214 functions.GetBufferSize = NULL;
1215
1216 if (!_mesa_initialize_context(&osmesa->mesa,
1217 osmesa->gl_visual,
1218 sharelist ? &sharelist->mesa
1219 : (GLcontext *) NULL,
1220 &functions, (void *) osmesa)) {
1221 _mesa_destroy_visual( osmesa->gl_visual );
1222 _mesa_free(osmesa);
1223 return NULL;
1224 }
1225
1226 _mesa_enable_sw_extensions(&(osmesa->mesa));
1227 _mesa_enable_1_3_extensions(&(osmesa->mesa));
1228 _mesa_enable_1_4_extensions(&(osmesa->mesa));
1229 _mesa_enable_1_5_extensions(&(osmesa->mesa));
1230 _mesa_enable_2_0_extensions(&(osmesa->mesa));
1231 _mesa_enable_2_1_extensions(&(osmesa->mesa));
1232
1233 osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
1234 if (!osmesa->gl_buffer) {
1235 _mesa_destroy_visual( osmesa->gl_visual );
1236 _mesa_free_context_data( &osmesa->mesa );
1237 _mesa_free(osmesa);
1238 return NULL;
1239 }
1240
1241 /* create front color buffer in user-provided memory (no back buffer) */
1242 osmesa->rb = new_osmesa_renderbuffer(&osmesa->mesa, format, type);
1243 _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
1244 assert(osmesa->rb->RefCount == 2);
1245
1246 _mesa_add_soft_renderbuffers(osmesa->gl_buffer,
1247 GL_FALSE, /* color */
1248 osmesa->gl_visual->haveDepthBuffer,
1249 osmesa->gl_visual->haveStencilBuffer,
1250 osmesa->gl_visual->haveAccumBuffer,
1251 GL_FALSE, /* alpha */
1252 GL_FALSE /* aux */ );
1253
1254 osmesa->format = format;
1255 osmesa->userRowLength = 0;
1256 osmesa->yup = GL_TRUE;
1257 osmesa->rInd = rind;
1258 osmesa->gInd = gind;
1259 osmesa->bInd = bind;
1260 osmesa->aInd = aind;
1261
1262 _mesa_meta_init(&osmesa->mesa);
1263
1264 /* Initialize the software rasterizer and helper modules. */
1265 {
1266 GLcontext *ctx = &osmesa->mesa;
1267 SWcontext *swrast;
1268 TNLcontext *tnl;
1269
1270 if (!_swrast_CreateContext( ctx ) ||
1271 !_vbo_CreateContext( ctx ) ||
1272 !_tnl_CreateContext( ctx ) ||
1273 !_swsetup_CreateContext( ctx )) {
1274 _mesa_destroy_visual(osmesa->gl_visual);
1275 _mesa_free_context_data(ctx);
1276 _mesa_free(osmesa);
1277 return NULL;
1278 }
1279
1280 _swsetup_Wakeup( ctx );
1281
1282 /* use default TCL pipeline */
1283 tnl = TNL_CONTEXT(ctx);
1284 tnl->Driver.RunPipeline = _tnl_run_pipeline;
1285
1286 /* Extend the software rasterizer with our optimized line and triangle
1287 * drawing functions.
1288 */
1289 swrast = SWRAST_CONTEXT( ctx );
1290 swrast->choose_line = osmesa_choose_line;
1291 swrast->choose_triangle = osmesa_choose_triangle;
1292 }
1293 }
1294 return osmesa;
1295 }
1296
1297
1298 /**
1299 * Destroy an Off-Screen Mesa rendering context.
1300 *
1301 * \param osmesa the context to destroy
1302 */
1303 GLAPI void GLAPIENTRY
1304 OSMesaDestroyContext( OSMesaContext osmesa )
1305 {
1306 if (osmesa) {
1307 if (osmesa->rb)
1308 _mesa_reference_renderbuffer(&osmesa->rb, NULL);
1309
1310 _mesa_meta_free( &osmesa->mesa );
1311
1312 _swsetup_DestroyContext( &osmesa->mesa );
1313 _tnl_DestroyContext( &osmesa->mesa );
1314 _vbo_DestroyContext( &osmesa->mesa );
1315 _swrast_DestroyContext( &osmesa->mesa );
1316
1317 _mesa_destroy_visual( osmesa->gl_visual );
1318 _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL );
1319
1320 _mesa_free_context_data( &osmesa->mesa );
1321 _mesa_free( osmesa );
1322 }
1323 }
1324
1325
1326 /**
1327 * Bind an OSMesaContext to an image buffer. The image buffer is just a
1328 * block of memory which the client provides. Its size must be at least
1329 * as large as width*height*sizeof(type). Its address should be a multiple
1330 * of 4 if using RGBA mode.
1331 *
1332 * Image data is stored in the order of glDrawPixels: row-major order
1333 * with the lower-left image pixel stored in the first array position
1334 * (ie. bottom-to-top).
1335 *
1336 * If the context's viewport hasn't been initialized yet, it will now be
1337 * initialized to (0,0,width,height).
1338 *
1339 * Input: osmesa - the rendering context
1340 * buffer - the image buffer memory
1341 * type - data type for pixel components
1342 * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
1343 * are supported. But if Mesa's been compiled with CHAN_BITS==16
1344 * then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. And if
1345 * Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT,
1346 * GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.
1347 * width, height - size of image buffer in pixels, at least 1
1348 * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
1349 * invalid buffer address, invalid type, width<1, height<1,
1350 * width>internal limit or height>internal limit.
1351 */
1352 GLAPI GLboolean GLAPIENTRY
1353 OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type,
1354 GLsizei width, GLsizei height )
1355 {
1356 if (!osmesa || !buffer ||
1357 width < 1 || height < 1 ||
1358 width > MAX_WIDTH || height > MAX_HEIGHT) {
1359 return GL_FALSE;
1360 }
1361
1362 if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
1363 return GL_FALSE;
1364 }
1365
1366 #if 0
1367 if (!(type == GL_UNSIGNED_BYTE ||
1368 (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) ||
1369 (type == GL_FLOAT && CHAN_BITS == 32))) {
1370 /* i.e. is sizeof(type) * 8 > CHAN_BITS? */
1371 return GL_FALSE;
1372 }
1373 #endif
1374
1375 osmesa_update_state( &osmesa->mesa, 0 );
1376
1377 /* Call this periodically to detect when the user has begun using
1378 * GL rendering from multiple threads.
1379 */
1380 _glapi_check_multithread();
1381
1382 /* Set renderbuffer fields. Set width/height = 0 to force
1383 * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer()
1384 */
1385 osmesa->rb->Data = buffer;
1386 osmesa->rb->DataType = type;
1387 osmesa->rb->Width = osmesa->rb->Height = 0;
1388
1389 /* Set the framebuffer's size. This causes the
1390 * osmesa_renderbuffer_storage() function to get called.
1391 */
1392 _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
1393 osmesa->gl_buffer->Initialized = GL_TRUE; /* XXX TEMPORARY? */
1394
1395 _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer );
1396
1397 /* Remove renderbuffer attachment, then re-add. This installs the
1398 * renderbuffer adaptor/wrapper if needed (for bpp conversion).
1399 */
1400 _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
1401 _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
1402
1403
1404 /* this updates the visual's red/green/blue/alphaBits fields */
1405 _mesa_update_framebuffer_visual(osmesa->gl_buffer);
1406
1407 /* update the framebuffer size */
1408 _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
1409
1410 return GL_TRUE;
1411 }
1412
1413
1414
1415 GLAPI OSMesaContext GLAPIENTRY
1416 OSMesaGetCurrentContext( void )
1417 {
1418 GLcontext *ctx = _mesa_get_current_context();
1419 if (ctx)
1420 return (OSMesaContext) ctx;
1421 else
1422 return NULL;
1423 }
1424
1425
1426
1427 GLAPI void GLAPIENTRY
1428 OSMesaPixelStore( GLint pname, GLint value )
1429 {
1430 OSMesaContext osmesa = OSMesaGetCurrentContext();
1431
1432 switch (pname) {
1433 case OSMESA_ROW_LENGTH:
1434 if (value<0) {
1435 _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
1436 "OSMesaPixelStore(value)" );
1437 return;
1438 }
1439 osmesa->userRowLength = value;
1440 break;
1441 case OSMESA_Y_UP:
1442 osmesa->yup = value ? GL_TRUE : GL_FALSE;
1443 break;
1444 default:
1445 _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
1446 return;
1447 }
1448
1449 compute_row_addresses( osmesa );
1450 }
1451
1452
1453 GLAPI void GLAPIENTRY
1454 OSMesaGetIntegerv( GLint pname, GLint *value )
1455 {
1456 OSMesaContext osmesa = OSMesaGetCurrentContext();
1457
1458 switch (pname) {
1459 case OSMESA_WIDTH:
1460 if (osmesa->gl_buffer)
1461 *value = osmesa->gl_buffer->Width;
1462 else
1463 *value = 0;
1464 return;
1465 case OSMESA_HEIGHT:
1466 if (osmesa->gl_buffer)
1467 *value = osmesa->gl_buffer->Height;
1468 else
1469 *value = 0;
1470 return;
1471 case OSMESA_FORMAT:
1472 *value = osmesa->format;
1473 return;
1474 case OSMESA_TYPE:
1475 /* current color buffer's data type */
1476 if (osmesa->rb) {
1477 *value = osmesa->rb->DataType;
1478 }
1479 else {
1480 *value = 0;
1481 }
1482 return;
1483 case OSMESA_ROW_LENGTH:
1484 *value = osmesa->userRowLength;
1485 return;
1486 case OSMESA_Y_UP:
1487 *value = osmesa->yup;
1488 return;
1489 case OSMESA_MAX_WIDTH:
1490 *value = MAX_WIDTH;
1491 return;
1492 case OSMESA_MAX_HEIGHT:
1493 *value = MAX_HEIGHT;
1494 return;
1495 default:
1496 _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1497 return;
1498 }
1499 }
1500
1501
1502 /**
1503 * Return the depth buffer associated with an OSMesa context.
1504 * Input: c - the OSMesa context
1505 * Output: width, height - size of buffer in pixels
1506 * bytesPerValue - bytes per depth value (2 or 4)
1507 * buffer - pointer to depth buffer values
1508 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1509 */
1510 GLAPI GLboolean GLAPIENTRY
1511 OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1512 GLint *bytesPerValue, void **buffer )
1513 {
1514 struct gl_renderbuffer *rb = NULL;
1515
1516 if (c->gl_buffer)
1517 rb = c->gl_buffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1518
1519 if (!rb || !rb->Data) {
1520 *width = 0;
1521 *height = 0;
1522 *bytesPerValue = 0;
1523 *buffer = 0;
1524 return GL_FALSE;
1525 }
1526 else {
1527 *width = rb->Width;
1528 *height = rb->Height;
1529 if (c->gl_visual->depthBits <= 16)
1530 *bytesPerValue = sizeof(GLushort);
1531 else
1532 *bytesPerValue = sizeof(GLuint);
1533 *buffer = rb->Data;
1534 return GL_TRUE;
1535 }
1536 }
1537
1538
1539 /**
1540 * Return the color buffer associated with an OSMesa context.
1541 * Input: c - the OSMesa context
1542 * Output: width, height - size of buffer in pixels
1543 * format - the pixel format (OSMESA_FORMAT)
1544 * buffer - pointer to color buffer values
1545 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1546 */
1547 GLAPI GLboolean GLAPIENTRY
1548 OSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width,
1549 GLint *height, GLint *format, void **buffer )
1550 {
1551 if (osmesa->rb && osmesa->rb->Data) {
1552 *width = osmesa->rb->Width;
1553 *height = osmesa->rb->Height;
1554 *format = osmesa->format;
1555 *buffer = osmesa->rb->Data;
1556 return GL_TRUE;
1557 }
1558 else {
1559 *width = 0;
1560 *height = 0;
1561 *format = 0;
1562 *buffer = 0;
1563 return GL_FALSE;
1564 }
1565 }
1566
1567
1568 struct name_function
1569 {
1570 const char *Name;
1571 OSMESAproc Function;
1572 };
1573
1574 static struct name_function functions[] = {
1575 { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
1576 { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
1577 { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
1578 { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
1579 { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
1580 { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
1581 { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
1582 { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1583 { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1584 { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1585 { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
1586 { NULL, NULL }
1587 };
1588
1589
1590 GLAPI OSMESAproc GLAPIENTRY
1591 OSMesaGetProcAddress( const char *funcName )
1592 {
1593 int i;
1594 for (i = 0; functions[i].Name; i++) {
1595 if (_mesa_strcmp(functions[i].Name, funcName) == 0)
1596 return functions[i].Function;
1597 }
1598 return _glapi_get_proc_address(funcName);
1599 }
1600
1601
1602 GLAPI void GLAPIENTRY
1603 OSMesaColorClamp(GLboolean enable)
1604 {
1605 OSMesaContext osmesa = OSMesaGetCurrentContext();
1606
1607 if (enable == GL_TRUE) {
1608 osmesa->mesa.Color.ClampFragmentColor = GL_TRUE;
1609 }
1610 else {
1611 osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
1612 }
1613 }
1614
1615