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