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