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