1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg
26848b8605Smrg/*
27848b8605Smrg * Off-Screen Mesa rendering / Rendering into client memory space
28848b8605Smrg *
29848b8605Smrg * Note on thread safety:  this driver is thread safe.  All
30848b8605Smrg * functions are reentrant.  The notion of current context is
31848b8605Smrg * managed by the core _mesa_make_current() and _mesa_get_current_context()
32848b8605Smrg * functions.  Those functions are thread-safe.
33848b8605Smrg */
34848b8605Smrg
35848b8605Smrg
36b8e80941Smrg#include <stdio.h>
37848b8605Smrg#include "main/glheader.h"
38848b8605Smrg#include "GL/osmesa.h"
39848b8605Smrg#include "main/api_exec.h"
40848b8605Smrg#include "main/context.h"
41848b8605Smrg#include "main/extensions.h"
42848b8605Smrg#include "main/formats.h"
43848b8605Smrg#include "main/framebuffer.h"
44848b8605Smrg#include "main/imports.h"
45848b8605Smrg#include "main/macros.h"
46848b8605Smrg#include "main/mipmap.h"
47848b8605Smrg#include "main/mtypes.h"
48848b8605Smrg#include "main/renderbuffer.h"
49848b8605Smrg#include "main/version.h"
50848b8605Smrg#include "main/vtxfmt.h"
51848b8605Smrg#include "swrast/swrast.h"
52848b8605Smrg#include "swrast_setup/swrast_setup.h"
53848b8605Smrg#include "swrast/s_context.h"
54848b8605Smrg#include "swrast/s_lines.h"
55848b8605Smrg#include "swrast/s_renderbuffer.h"
56848b8605Smrg#include "swrast/s_triangle.h"
57848b8605Smrg#include "tnl/tnl.h"
58848b8605Smrg#include "tnl/t_context.h"
59848b8605Smrg#include "tnl/t_pipeline.h"
60848b8605Smrg#include "drivers/common/driverfuncs.h"
61848b8605Smrg#include "drivers/common/meta.h"
62848b8605Smrg#include "vbo/vbo.h"
63848b8605Smrg
64848b8605Smrg
65848b8605Smrg#define OSMESA_RENDERBUFFER_CLASS 0x053
66848b8605Smrg
67848b8605Smrg
68848b8605Smrg/**
69848b8605Smrg * OSMesa rendering context, derived from core Mesa struct gl_context.
70848b8605Smrg */
71848b8605Smrgstruct osmesa_context
72848b8605Smrg{
73848b8605Smrg   struct gl_context mesa;		/*< Base class - this must be first */
74848b8605Smrg   struct gl_config *gl_visual;		/*< Describes the buffers */
75848b8605Smrg   struct swrast_renderbuffer *srb;     /*< The user's colorbuffer */
76848b8605Smrg   struct gl_framebuffer *gl_buffer;	/*< The framebuffer, containing user's rb */
77848b8605Smrg   GLenum format;		/*< User-specified context format */
78848b8605Smrg   GLint userRowLength;		/*< user-specified number of pixels per row */
79848b8605Smrg   GLint rInd, gInd, bInd, aInd;/*< index offsets for RGBA formats */
80848b8605Smrg   GLvoid *rowaddr[SWRAST_MAX_HEIGHT];	/*< address of first pixel in each image row */
81848b8605Smrg   GLboolean yup;		/*< TRUE  -> Y increases upward */
82848b8605Smrg				/*< FALSE -> Y increases downward */
83848b8605Smrg   GLenum DataType;
84848b8605Smrg};
85848b8605Smrg
86848b8605Smrg
87b8e80941Smrgstatic inline OSMesaContext
88848b8605SmrgOSMESA_CONTEXT(struct gl_context *ctx)
89848b8605Smrg{
90848b8605Smrg   /* Just cast, since we're using structure containment */
91848b8605Smrg   return (OSMesaContext) ctx;
92848b8605Smrg}
93848b8605Smrg
94848b8605Smrg
95848b8605Smrg/**********************************************************************/
96848b8605Smrg/*** Private Device Driver Functions                                ***/
97848b8605Smrg/**********************************************************************/
98848b8605Smrg
99848b8605Smrg
100848b8605Smrgstatic const GLubyte *
101848b8605Smrgget_string( struct gl_context *ctx, GLenum name )
102848b8605Smrg{
103848b8605Smrg   (void) ctx;
104848b8605Smrg   switch (name) {
105848b8605Smrg      case GL_RENDERER:
106848b8605Smrg#if CHAN_BITS == 32
107848b8605Smrg         return (const GLubyte *) "Mesa OffScreen32";
108848b8605Smrg#elif CHAN_BITS == 16
109848b8605Smrg         return (const GLubyte *) "Mesa OffScreen16";
110848b8605Smrg#else
111848b8605Smrg         return (const GLubyte *) "Mesa OffScreen";
112848b8605Smrg#endif
113848b8605Smrg      default:
114848b8605Smrg         return NULL;
115848b8605Smrg   }
116848b8605Smrg}
117848b8605Smrg
118848b8605Smrg
119848b8605Smrgstatic void
120b8e80941Smrgosmesa_update_state(struct gl_context *ctx, GLuint new_state)
121848b8605Smrg{
122b8e80941Smrg   if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
123b8e80941Smrg      _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
124b8e80941Smrg
125848b8605Smrg   /* easy - just propogate */
126848b8605Smrg   _swrast_InvalidateState( ctx, new_state );
127848b8605Smrg   _swsetup_InvalidateState( ctx, new_state );
128848b8605Smrg   _tnl_InvalidateState( ctx, new_state );
129848b8605Smrg}
130848b8605Smrg
131b8e80941Smrgstatic void
132b8e80941Smrgosmesa_update_state_wrapper(struct gl_context *ctx)
133b8e80941Smrg{
134b8e80941Smrg   osmesa_update_state(ctx, ctx->NewState);
135b8e80941Smrg}
136848b8605Smrg
137848b8605Smrg
138848b8605Smrg/**
139848b8605Smrg * Macros for optimized line/triangle rendering.
140848b8605Smrg * Only for 8-bit channel, RGBA, BGRA, ARGB formats.
141848b8605Smrg */
142848b8605Smrg
143848b8605Smrg#define PACK_RGBA(DST, R, G, B, A)	\
144848b8605Smrgdo {					\
145848b8605Smrg   (DST)[osmesa->rInd] = R;		\
146848b8605Smrg   (DST)[osmesa->gInd] = G;		\
147848b8605Smrg   (DST)[osmesa->bInd] = B;		\
148848b8605Smrg   (DST)[osmesa->aInd] = A;		\
149848b8605Smrg} while (0)
150848b8605Smrg
151848b8605Smrg#define PIXELADDR4(X,Y)  ((GLchan *) osmesa->rowaddr[Y] + 4 * (X))
152848b8605Smrg
153848b8605Smrg
154848b8605Smrg/**
155848b8605Smrg * Draw a flat-shaded, RGB line into an osmesa buffer.
156848b8605Smrg */
157848b8605Smrg#define NAME flat_rgba_line
158848b8605Smrg#define CLIP_HACK 1
159848b8605Smrg#define SETUP_CODE						\
160848b8605Smrg   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
161848b8605Smrg   const GLchan *color = vert1->color;
162848b8605Smrg
163848b8605Smrg#define PLOT(X, Y)						\
164848b8605Smrgdo {								\
165848b8605Smrg   GLchan *p = PIXELADDR4(X, Y);				\
166848b8605Smrg   PACK_RGBA(p, color[0], color[1], color[2], color[3]);	\
167848b8605Smrg} while (0)
168848b8605Smrg
169848b8605Smrg#include "swrast/s_linetemp.h"
170848b8605Smrg
171848b8605Smrg
172848b8605Smrg
173848b8605Smrg/**
174848b8605Smrg * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
175848b8605Smrg */
176848b8605Smrg#define NAME flat_rgba_z_line
177848b8605Smrg#define CLIP_HACK 1
178848b8605Smrg#define INTERP_Z 1
179848b8605Smrg#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
180848b8605Smrg#define SETUP_CODE					\
181848b8605Smrg   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);	\
182848b8605Smrg   const GLchan *color = vert1->color;
183848b8605Smrg
184848b8605Smrg#define PLOT(X, Y)					\
185848b8605Smrgdo {							\
186848b8605Smrg   if (Z < *zPtr) {					\
187848b8605Smrg      GLchan *p = PIXELADDR4(X, Y);			\
188848b8605Smrg      PACK_RGBA(p, color[RCOMP], color[GCOMP],		\
189848b8605Smrg                   color[BCOMP], color[ACOMP]);		\
190848b8605Smrg      *zPtr = Z;					\
191848b8605Smrg   }							\
192848b8605Smrg} while (0)
193848b8605Smrg
194848b8605Smrg#include "swrast/s_linetemp.h"
195848b8605Smrg
196848b8605Smrg
197848b8605Smrg
198848b8605Smrg/**
199848b8605Smrg * Analyze context state to see if we can provide a fast line drawing
200848b8605Smrg * function.  Otherwise, return NULL.
201848b8605Smrg */
202848b8605Smrgstatic swrast_line_func
203848b8605Smrgosmesa_choose_line_function( struct gl_context *ctx )
204848b8605Smrg{
205848b8605Smrg   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
206848b8605Smrg   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
207848b8605Smrg
208848b8605Smrg   if (ctx->DrawBuffer &&
209848b8605Smrg       ctx->DrawBuffer->Visual.redBits == 32) {
210848b8605Smrg      /* the special-case line functions in this file don't work
211848b8605Smrg       * for float color channels.
212848b8605Smrg       */
213848b8605Smrg      return NULL;
214848b8605Smrg   }
215848b8605Smrg
216848b8605Smrg   if (ctx->RenderMode != GL_RENDER ||
217848b8605Smrg       ctx->Texture._MaxEnabledTexImageUnit == -1 ||
218848b8605Smrg       ctx->Light.ShadeModel != GL_FLAT ||
219848b8605Smrg       ctx->Line.Width != 1.0F ||
220848b8605Smrg       ctx->Line.StippleFlag ||
221848b8605Smrg       ctx->Line.SmoothFlag) {
222848b8605Smrg      return NULL;
223848b8605Smrg   }
224848b8605Smrg
225848b8605Smrg   if (osmesa->format != OSMESA_RGBA &&
226848b8605Smrg       osmesa->format != OSMESA_BGRA &&
227848b8605Smrg       osmesa->format != OSMESA_ARGB) {
228848b8605Smrg      return NULL;
229848b8605Smrg   }
230848b8605Smrg
231848b8605Smrg   if (swrast->_RasterMask == DEPTH_BIT
232848b8605Smrg       && ctx->Depth.Func == GL_LESS
233848b8605Smrg       && ctx->Depth.Mask == GL_TRUE
234848b8605Smrg       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
235848b8605Smrg      return flat_rgba_z_line;
236848b8605Smrg   }
237848b8605Smrg
238848b8605Smrg   if (swrast->_RasterMask == 0) {
239848b8605Smrg      return flat_rgba_line;
240848b8605Smrg   }
241848b8605Smrg
242848b8605Smrg   return (swrast_line_func) NULL;
243848b8605Smrg}
244848b8605Smrg
245848b8605Smrg
246848b8605Smrg/**********************************************************************/
247848b8605Smrg/*****                 Optimized triangle rendering               *****/
248848b8605Smrg/**********************************************************************/
249848b8605Smrg
250848b8605Smrg
251848b8605Smrg/*
252848b8605Smrg * Smooth-shaded, z-less triangle, RGBA color.
253848b8605Smrg */
254848b8605Smrg#define NAME smooth_rgba_z_triangle
255848b8605Smrg#define INTERP_Z 1
256848b8605Smrg#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
257848b8605Smrg#define INTERP_RGB 1
258848b8605Smrg#define INTERP_ALPHA 1
259848b8605Smrg#define SETUP_CODE \
260848b8605Smrg   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
261848b8605Smrg#define RENDER_SPAN( span ) {					\
262848b8605Smrg   GLuint i;							\
263848b8605Smrg   GLchan *img = PIXELADDR4(span.x, span.y); 			\
264848b8605Smrg   for (i = 0; i < span.end; i++, img += 4) {			\
265848b8605Smrg      const GLuint z = FixedToDepth(span.z);			\
266848b8605Smrg      if (z < zRow[i]) {					\
267848b8605Smrg         PACK_RGBA(img, FixedToChan(span.red),			\
268848b8605Smrg            FixedToChan(span.green), FixedToChan(span.blue),	\
269848b8605Smrg            FixedToChan(span.alpha));				\
270848b8605Smrg         zRow[i] = z;						\
271848b8605Smrg      }								\
272848b8605Smrg      span.red += span.redStep;					\
273848b8605Smrg      span.green += span.greenStep;				\
274848b8605Smrg      span.blue += span.blueStep;				\
275848b8605Smrg      span.alpha += span.alphaStep;				\
276848b8605Smrg      span.z += span.zStep;					\
277848b8605Smrg   }                                                            \
278848b8605Smrg}
279848b8605Smrg#include "swrast/s_tritemp.h"
280848b8605Smrg
281848b8605Smrg
282848b8605Smrg
283848b8605Smrg/*
284848b8605Smrg * Flat-shaded, z-less triangle, RGBA color.
285848b8605Smrg */
286848b8605Smrg#define NAME flat_rgba_z_triangle
287848b8605Smrg#define INTERP_Z 1
288848b8605Smrg#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
289848b8605Smrg#define SETUP_CODE						\
290848b8605Smrg   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
291848b8605Smrg   GLuint pixel;						\
292848b8605Smrg   PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1],	\
293848b8605Smrg                                v2->color[2], v2->color[3]);
294848b8605Smrg
295848b8605Smrg#define RENDER_SPAN( span ) {				\
296848b8605Smrg   GLuint i;						\
297848b8605Smrg   GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y);	\
298848b8605Smrg   for (i = 0; i < span.end; i++) {			\
299848b8605Smrg      const GLuint z = FixedToDepth(span.z);		\
300848b8605Smrg      if (z < zRow[i]) {				\
301848b8605Smrg         img[i] = pixel;				\
302848b8605Smrg         zRow[i] = z;					\
303848b8605Smrg      }							\
304848b8605Smrg      span.z += span.zStep;				\
305848b8605Smrg   }                                                    \
306848b8605Smrg}
307848b8605Smrg
308848b8605Smrg#include "swrast/s_tritemp.h"
309848b8605Smrg
310848b8605Smrg
311848b8605Smrg
312848b8605Smrg/**
313848b8605Smrg * Return pointer to an optimized triangle function if possible.
314848b8605Smrg */
315848b8605Smrgstatic swrast_tri_func
316848b8605Smrgosmesa_choose_triangle_function( struct gl_context *ctx )
317848b8605Smrg{
318848b8605Smrg   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
319848b8605Smrg   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
320848b8605Smrg
321848b8605Smrg   if (ctx->DrawBuffer &&
322848b8605Smrg       ctx->DrawBuffer->Visual.redBits == 32) {
323848b8605Smrg      /* the special-case triangle functions in this file don't work
324848b8605Smrg       * for float color channels.
325848b8605Smrg       */
326848b8605Smrg      return NULL;
327848b8605Smrg   }
328848b8605Smrg
329848b8605Smrg   if (ctx->RenderMode != GL_RENDER ||
330848b8605Smrg       ctx->Polygon.SmoothFlag ||
331848b8605Smrg       ctx->Polygon.StippleFlag ||
332848b8605Smrg       ctx->Texture._MaxEnabledTexImageUnit != -1) {
333848b8605Smrg      return NULL;
334848b8605Smrg   }
335848b8605Smrg
336848b8605Smrg   if (osmesa->format != OSMESA_RGBA &&
337848b8605Smrg       osmesa->format != OSMESA_BGRA &&
338848b8605Smrg       osmesa->format != OSMESA_ARGB) {
339848b8605Smrg      return NULL;
340848b8605Smrg   }
341848b8605Smrg
342848b8605Smrg   if (ctx->Polygon.CullFlag &&
343848b8605Smrg       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
344848b8605Smrg      return NULL;
345848b8605Smrg   }
346848b8605Smrg
347848b8605Smrg   if (swrast->_RasterMask == DEPTH_BIT &&
348848b8605Smrg       ctx->Depth.Func == GL_LESS &&
349848b8605Smrg       ctx->Depth.Mask == GL_TRUE &&
350848b8605Smrg       ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
351848b8605Smrg      if (ctx->Light.ShadeModel == GL_SMOOTH) {
352848b8605Smrg         return smooth_rgba_z_triangle;
353848b8605Smrg      }
354848b8605Smrg      else {
355848b8605Smrg         return flat_rgba_z_triangle;
356848b8605Smrg      }
357848b8605Smrg   }
358848b8605Smrg
359848b8605Smrg   return NULL;
360848b8605Smrg}
361848b8605Smrg
362848b8605Smrg
363848b8605Smrg
364848b8605Smrg/* Override for the swrast triangle-selection function.  Try to use one
365848b8605Smrg * of our internal triangle functions, otherwise fall back to the
366848b8605Smrg * standard swrast functions.
367848b8605Smrg */
368848b8605Smrgstatic void
369848b8605Smrgosmesa_choose_triangle( struct gl_context *ctx )
370848b8605Smrg{
371848b8605Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
372848b8605Smrg
373848b8605Smrg   swrast->Triangle = osmesa_choose_triangle_function( ctx );
374848b8605Smrg   if (!swrast->Triangle)
375848b8605Smrg      _swrast_choose_triangle( ctx );
376848b8605Smrg}
377848b8605Smrg
378848b8605Smrgstatic void
379848b8605Smrgosmesa_choose_line( struct gl_context *ctx )
380848b8605Smrg{
381848b8605Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
382848b8605Smrg
383848b8605Smrg   swrast->Line = osmesa_choose_line_function( ctx );
384848b8605Smrg   if (!swrast->Line)
385848b8605Smrg      _swrast_choose_line( ctx );
386848b8605Smrg}
387848b8605Smrg
388848b8605Smrg
389848b8605Smrg
390848b8605Smrg/**
391848b8605Smrg * Recompute the values of the context's rowaddr array.
392848b8605Smrg */
393848b8605Smrgstatic void
394848b8605Smrgcompute_row_addresses( OSMesaContext osmesa )
395848b8605Smrg{
396848b8605Smrg   GLint bytesPerRow, i;
397848b8605Smrg   GLubyte *origin = (GLubyte *) osmesa->srb->Buffer;
398848b8605Smrg   GLint rowlength; /* in pixels */
399848b8605Smrg   GLint height = osmesa->srb->Base.Height;
400848b8605Smrg
401848b8605Smrg   if (osmesa->userRowLength)
402848b8605Smrg      rowlength = osmesa->userRowLength;
403848b8605Smrg   else
404848b8605Smrg      rowlength = osmesa->srb->Base.Width;
405848b8605Smrg
406848b8605Smrg   bytesPerRow = rowlength * _mesa_get_format_bytes(osmesa->srb->Base.Format);
407848b8605Smrg
408848b8605Smrg   if (osmesa->yup) {
409848b8605Smrg      /* Y=0 is bottom line of window */
410848b8605Smrg      for (i = 0; i < height; i++) {
411848b8605Smrg         osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + i * bytesPerRow);
412848b8605Smrg      }
413848b8605Smrg   }
414848b8605Smrg   else {
415848b8605Smrg      /* Y=0 is top line of window */
416848b8605Smrg      for (i = 0; i < height; i++) {
417848b8605Smrg         GLint j = height - i - 1;
418848b8605Smrg         osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + j * bytesPerRow);
419848b8605Smrg      }
420848b8605Smrg   }
421848b8605Smrg}
422848b8605Smrg
423848b8605Smrg
424848b8605Smrg
425848b8605Smrg/**
426848b8605Smrg * Don't use _mesa_delete_renderbuffer since we can't free rb->Buffer.
427848b8605Smrg */
428848b8605Smrgstatic void
429848b8605Smrgosmesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
430848b8605Smrg{
431848b8605Smrg   _mesa_delete_renderbuffer(ctx, rb);
432848b8605Smrg}
433848b8605Smrg
434848b8605Smrg
435848b8605Smrg/**
436848b8605Smrg * Allocate renderbuffer storage.  We don't actually allocate any storage
437848b8605Smrg * since we're using a user-provided buffer.
438848b8605Smrg * Just set up all the gl_renderbuffer methods.
439848b8605Smrg */
440848b8605Smrgstatic GLboolean
441848b8605Smrgosmesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
442848b8605Smrg                            GLenum internalFormat, GLuint width, GLuint height)
443848b8605Smrg{
444848b8605Smrg   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
445848b8605Smrg
446848b8605Smrg   /* Note: we can ignoring internalFormat for "window-system" renderbuffers */
447848b8605Smrg   (void) internalFormat;
448848b8605Smrg
449848b8605Smrg   /* Given the user-provided format and type, figure out which MESA_FORMAT_x
450848b8605Smrg    * to use.
451848b8605Smrg    * XXX There aren't Mesa formats for all the possible combinations here!
452848b8605Smrg    * XXX Specifically, there's only RGBA-order 16-bit/channel and float
453848b8605Smrg    * XXX formats.
454848b8605Smrg    * XXX The 8-bit/channel formats should all be OK.
455848b8605Smrg    */
456848b8605Smrg   if (osmesa->format == OSMESA_RGBA) {
457848b8605Smrg      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
458848b8605Smrg         if (_mesa_little_endian())
459848b8605Smrg            rb->Format = MESA_FORMAT_R8G8B8A8_UNORM;
460848b8605Smrg         else
461848b8605Smrg            rb->Format = MESA_FORMAT_A8B8G8R8_UNORM;
462848b8605Smrg      }
463848b8605Smrg      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
464848b8605Smrg         rb->Format = MESA_FORMAT_RGBA_UNORM16;
465848b8605Smrg      }
466848b8605Smrg      else {
467848b8605Smrg         rb->Format = MESA_FORMAT_RGBA_FLOAT32;
468848b8605Smrg      }
469848b8605Smrg   }
470848b8605Smrg   else if (osmesa->format == OSMESA_BGRA) {
471848b8605Smrg      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
472848b8605Smrg         if (_mesa_little_endian())
473848b8605Smrg            rb->Format = MESA_FORMAT_B8G8R8A8_UNORM;
474848b8605Smrg         else
475848b8605Smrg            rb->Format = MESA_FORMAT_A8R8G8B8_UNORM;
476848b8605Smrg      }
477848b8605Smrg      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
478848b8605Smrg         _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLushort");
479848b8605Smrg         rb->Format = MESA_FORMAT_RGBA_UNORM16; /* not exactly right */
480848b8605Smrg      }
481848b8605Smrg      else {
482848b8605Smrg         _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLfloat");
483848b8605Smrg         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
484848b8605Smrg      }
485848b8605Smrg   }
486848b8605Smrg   else if (osmesa->format == OSMESA_ARGB) {
487848b8605Smrg      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
488848b8605Smrg         if (_mesa_little_endian())
489848b8605Smrg            rb->Format = MESA_FORMAT_A8R8G8B8_UNORM;
490848b8605Smrg         else
491848b8605Smrg            rb->Format = MESA_FORMAT_B8G8R8A8_UNORM;
492848b8605Smrg      }
493848b8605Smrg      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
494848b8605Smrg         _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLushort");
495848b8605Smrg         rb->Format = MESA_FORMAT_RGBA_UNORM16; /* not exactly right */
496848b8605Smrg      }
497848b8605Smrg      else {
498848b8605Smrg         _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLfloat");
499848b8605Smrg         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
500848b8605Smrg      }
501848b8605Smrg   }
502848b8605Smrg   else if (osmesa->format == OSMESA_RGB) {
503848b8605Smrg      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
504848b8605Smrg         rb->Format = MESA_FORMAT_BGR_UNORM8;
505848b8605Smrg      }
506848b8605Smrg      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
507848b8605Smrg         _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLushort");
508848b8605Smrg         rb->Format = MESA_FORMAT_RGBA_UNORM16; /* not exactly right */
509848b8605Smrg      }
510848b8605Smrg      else {
511848b8605Smrg         _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLfloat");
512848b8605Smrg         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
513848b8605Smrg      }
514848b8605Smrg   }
515848b8605Smrg   else if (osmesa->format == OSMESA_BGR) {
516848b8605Smrg      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
517848b8605Smrg         rb->Format = MESA_FORMAT_RGB_UNORM8;
518848b8605Smrg      }
519848b8605Smrg      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
520848b8605Smrg         _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLushort");
521848b8605Smrg         rb->Format = MESA_FORMAT_RGBA_UNORM16; /* not exactly right */
522848b8605Smrg      }
523848b8605Smrg      else {
524848b8605Smrg         _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLfloat");
525848b8605Smrg         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
526848b8605Smrg      }
527848b8605Smrg   }
528848b8605Smrg   else if (osmesa->format == OSMESA_RGB_565) {
529b8e80941Smrg      assert(osmesa->DataType == GL_UNSIGNED_BYTE);
530848b8605Smrg      rb->Format = MESA_FORMAT_B5G6R5_UNORM;
531848b8605Smrg   }
532848b8605Smrg   else {
533848b8605Smrg      _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage");
534848b8605Smrg   }
535848b8605Smrg
536848b8605Smrg   rb->Width = width;
537848b8605Smrg   rb->Height = height;
538848b8605Smrg
539848b8605Smrg   compute_row_addresses( osmesa );
540848b8605Smrg
541848b8605Smrg   return GL_TRUE;
542848b8605Smrg}
543848b8605Smrg
544848b8605Smrg
545848b8605Smrg/**
546848b8605Smrg * Allocate a new renderbuffer to describe the user-provided color buffer.
547848b8605Smrg */
548848b8605Smrgstatic struct swrast_renderbuffer *
549848b8605Smrgnew_osmesa_renderbuffer(struct gl_context *ctx, GLenum format, GLenum type)
550848b8605Smrg{
551848b8605Smrg   const GLuint name = 0;
552848b8605Smrg   struct swrast_renderbuffer *srb = CALLOC_STRUCT(swrast_renderbuffer);
553848b8605Smrg
554848b8605Smrg   if (srb) {
555848b8605Smrg      _mesa_init_renderbuffer(&srb->Base, name);
556848b8605Smrg
557848b8605Smrg      srb->Base.ClassID = OSMESA_RENDERBUFFER_CLASS;
558848b8605Smrg      srb->Base.Delete = osmesa_delete_renderbuffer;
559848b8605Smrg      srb->Base.AllocStorage = osmesa_renderbuffer_storage;
560848b8605Smrg
561848b8605Smrg      srb->Base.InternalFormat = GL_RGBA;
562848b8605Smrg      srb->Base._BaseFormat = GL_RGBA;
563848b8605Smrg
564848b8605Smrg      return srb;
565848b8605Smrg   }
566848b8605Smrg   return NULL;
567848b8605Smrg}
568848b8605Smrg
569848b8605Smrg
570848b8605Smrg
571848b8605Smrgstatic void
572848b8605Smrgosmesa_MapRenderbuffer(struct gl_context *ctx,
573848b8605Smrg                       struct gl_renderbuffer *rb,
574848b8605Smrg                       GLuint x, GLuint y, GLuint w, GLuint h,
575848b8605Smrg                       GLbitfield mode,
576b8e80941Smrg                       GLubyte **mapOut, GLint *rowStrideOut,
577b8e80941Smrg                       bool flip_y)
578848b8605Smrg{
579848b8605Smrg   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
580848b8605Smrg
581848b8605Smrg   if (rb->ClassID == OSMESA_RENDERBUFFER_CLASS) {
582848b8605Smrg      /* this is an OSMesa renderbuffer which wraps user memory */
583848b8605Smrg      struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
584848b8605Smrg      const GLuint bpp = _mesa_get_format_bytes(rb->Format);
585848b8605Smrg      GLint rowStride; /* in bytes */
586848b8605Smrg
587848b8605Smrg      if (osmesa->userRowLength)
588848b8605Smrg         rowStride = osmesa->userRowLength * bpp;
589848b8605Smrg      else
590848b8605Smrg         rowStride = rb->Width * bpp;
591848b8605Smrg
592848b8605Smrg      if (!osmesa->yup) {
593848b8605Smrg         /* Y=0 is top line of window */
594848b8605Smrg         y = rb->Height - y - 1;
595848b8605Smrg         *rowStrideOut = -rowStride;
596848b8605Smrg      }
597848b8605Smrg      else {
598848b8605Smrg         *rowStrideOut = rowStride;
599848b8605Smrg      }
600848b8605Smrg
601848b8605Smrg      *mapOut = (GLubyte *) srb->Buffer + y * rowStride + x * bpp;
602848b8605Smrg   }
603848b8605Smrg   else {
604848b8605Smrg      _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode,
605b8e80941Smrg                                    mapOut, rowStrideOut, flip_y);
606848b8605Smrg   }
607848b8605Smrg}
608848b8605Smrg
609848b8605Smrg
610848b8605Smrgstatic void
611848b8605Smrgosmesa_UnmapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
612848b8605Smrg{
613848b8605Smrg   if (rb->ClassID == OSMESA_RENDERBUFFER_CLASS) {
614848b8605Smrg      /* no-op */
615848b8605Smrg   }
616848b8605Smrg   else {
617848b8605Smrg      _swrast_unmap_soft_renderbuffer(ctx, rb);
618848b8605Smrg   }
619848b8605Smrg}
620848b8605Smrg
621848b8605Smrg
622848b8605Smrg/**********************************************************************/
623848b8605Smrg/*****                    Public Functions                        *****/
624848b8605Smrg/**********************************************************************/
625848b8605Smrg
626848b8605Smrg
627848b8605Smrg/**
628848b8605Smrg * Create an Off-Screen Mesa rendering context.  The only attribute needed is
629848b8605Smrg * an RGBA vs Color-Index mode flag.
630848b8605Smrg *
631848b8605Smrg * Input:  format - Must be GL_RGBA
632848b8605Smrg *         sharelist - specifies another OSMesaContext with which to share
633848b8605Smrg *                     display lists.  NULL indicates no sharing.
634848b8605Smrg * Return:  an OSMesaContext or 0 if error
635848b8605Smrg */
636848b8605SmrgGLAPI OSMesaContext GLAPIENTRY
637848b8605SmrgOSMesaCreateContext( GLenum format, OSMesaContext sharelist )
638848b8605Smrg{
639848b8605Smrg   return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
640848b8605Smrg                                 8, 0, sharelist);
641848b8605Smrg}
642848b8605Smrg
643848b8605Smrg
644848b8605Smrg
645848b8605Smrg/**
646848b8605Smrg * New in Mesa 3.5
647848b8605Smrg *
648848b8605Smrg * Create context and specify size of ancillary buffers.
649848b8605Smrg */
650848b8605SmrgGLAPI OSMesaContext GLAPIENTRY
651848b8605SmrgOSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
652848b8605Smrg                        GLint accumBits, OSMesaContext sharelist )
653b8e80941Smrg{
654b8e80941Smrg   int attribs[100], n = 0;
655b8e80941Smrg
656b8e80941Smrg   attribs[n++] = OSMESA_FORMAT;
657b8e80941Smrg   attribs[n++] = format;
658b8e80941Smrg   attribs[n++] = OSMESA_DEPTH_BITS;
659b8e80941Smrg   attribs[n++] = depthBits;
660b8e80941Smrg   attribs[n++] = OSMESA_STENCIL_BITS;
661b8e80941Smrg   attribs[n++] = stencilBits;
662b8e80941Smrg   attribs[n++] = OSMESA_ACCUM_BITS;
663b8e80941Smrg   attribs[n++] = accumBits;
664b8e80941Smrg   attribs[n++] = 0;
665b8e80941Smrg
666b8e80941Smrg   return OSMesaCreateContextAttribs(attribs, sharelist);
667b8e80941Smrg}
668b8e80941Smrg
669b8e80941Smrg
670b8e80941Smrg/**
671b8e80941Smrg * New in Mesa 11.2
672b8e80941Smrg *
673b8e80941Smrg * Create context with attribute list.
674b8e80941Smrg */
675b8e80941SmrgGLAPI OSMesaContext GLAPIENTRY
676b8e80941SmrgOSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist)
677848b8605Smrg{
678848b8605Smrg   OSMesaContext osmesa;
679848b8605Smrg   struct dd_function_table functions;
680848b8605Smrg   GLint rind, gind, bind, aind;
681848b8605Smrg   GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
682b8e80941Smrg   GLenum format = OSMESA_RGBA;
683b8e80941Smrg   GLint depthBits = 0, stencilBits = 0, accumBits = 0;
684b8e80941Smrg   int profile = OSMESA_COMPAT_PROFILE, version_major = 1, version_minor = 0;
685b8e80941Smrg   gl_api api_profile = API_OPENGL_COMPAT;
686b8e80941Smrg   int i;
687b8e80941Smrg
688b8e80941Smrg   for (i = 0; attribList[i]; i += 2) {
689b8e80941Smrg      switch (attribList[i]) {
690b8e80941Smrg      case OSMESA_FORMAT:
691b8e80941Smrg         format = attribList[i+1];
692b8e80941Smrg         switch (format) {
693b8e80941Smrg         case OSMESA_COLOR_INDEX:
694b8e80941Smrg         case OSMESA_RGBA:
695b8e80941Smrg         case OSMESA_BGRA:
696b8e80941Smrg         case OSMESA_ARGB:
697b8e80941Smrg         case OSMESA_RGB:
698b8e80941Smrg         case OSMESA_BGR:
699b8e80941Smrg         case OSMESA_RGB_565:
700b8e80941Smrg            /* legal */
701b8e80941Smrg            break;
702b8e80941Smrg         default:
703b8e80941Smrg            return NULL;
704b8e80941Smrg         }
705b8e80941Smrg         break;
706b8e80941Smrg      case OSMESA_DEPTH_BITS:
707b8e80941Smrg         depthBits = attribList[i+1];
708b8e80941Smrg         if (depthBits < 0)
709b8e80941Smrg            return NULL;
710b8e80941Smrg         break;
711b8e80941Smrg      case OSMESA_STENCIL_BITS:
712b8e80941Smrg         stencilBits = attribList[i+1];
713b8e80941Smrg         if (stencilBits < 0)
714b8e80941Smrg            return NULL;
715b8e80941Smrg         break;
716b8e80941Smrg      case OSMESA_ACCUM_BITS:
717b8e80941Smrg         accumBits = attribList[i+1];
718b8e80941Smrg         if (accumBits < 0)
719b8e80941Smrg            return NULL;
720b8e80941Smrg         break;
721b8e80941Smrg      case OSMESA_PROFILE:
722b8e80941Smrg         profile = attribList[i+1];
723b8e80941Smrg         if (profile == OSMESA_COMPAT_PROFILE)
724b8e80941Smrg            api_profile = API_OPENGL_COMPAT;
725b8e80941Smrg         else if (profile == OSMESA_CORE_PROFILE)
726b8e80941Smrg            api_profile = API_OPENGL_CORE;
727b8e80941Smrg         else
728b8e80941Smrg            return NULL;
729b8e80941Smrg         break;
730b8e80941Smrg      case OSMESA_CONTEXT_MAJOR_VERSION:
731b8e80941Smrg         version_major = attribList[i+1];
732b8e80941Smrg         if (version_major < 1)
733b8e80941Smrg            return NULL;
734b8e80941Smrg         break;
735b8e80941Smrg      case OSMESA_CONTEXT_MINOR_VERSION:
736b8e80941Smrg         version_minor = attribList[i+1];
737b8e80941Smrg         if (version_minor < 0)
738b8e80941Smrg            return NULL;
739b8e80941Smrg         break;
740b8e80941Smrg      case 0:
741b8e80941Smrg         /* end of list */
742b8e80941Smrg         break;
743b8e80941Smrg      default:
744b8e80941Smrg         fprintf(stderr, "Bad attribute in OSMesaCreateContextAttribs()\n");
745b8e80941Smrg         return NULL;
746b8e80941Smrg      }
747b8e80941Smrg   }
748848b8605Smrg
749848b8605Smrg   rind = gind = bind = aind = 0;
750848b8605Smrg   if (format==OSMESA_RGBA) {
751848b8605Smrg      redBits = CHAN_BITS;
752848b8605Smrg      greenBits = CHAN_BITS;
753848b8605Smrg      blueBits = CHAN_BITS;
754848b8605Smrg      alphaBits = CHAN_BITS;
755848b8605Smrg      rind = 0;
756848b8605Smrg      gind = 1;
757848b8605Smrg      bind = 2;
758848b8605Smrg      aind = 3;
759848b8605Smrg   }
760848b8605Smrg   else if (format==OSMESA_BGRA) {
761848b8605Smrg      redBits = CHAN_BITS;
762848b8605Smrg      greenBits = CHAN_BITS;
763848b8605Smrg      blueBits = CHAN_BITS;
764848b8605Smrg      alphaBits = CHAN_BITS;
765848b8605Smrg      bind = 0;
766848b8605Smrg      gind = 1;
767848b8605Smrg      rind = 2;
768848b8605Smrg      aind = 3;
769848b8605Smrg   }
770848b8605Smrg   else if (format==OSMESA_ARGB) {
771848b8605Smrg      redBits = CHAN_BITS;
772848b8605Smrg      greenBits = CHAN_BITS;
773848b8605Smrg      blueBits = CHAN_BITS;
774848b8605Smrg      alphaBits = CHAN_BITS;
775848b8605Smrg      aind = 0;
776848b8605Smrg      rind = 1;
777848b8605Smrg      gind = 2;
778848b8605Smrg      bind = 3;
779848b8605Smrg   }
780848b8605Smrg   else if (format==OSMESA_RGB) {
781848b8605Smrg      redBits = CHAN_BITS;
782848b8605Smrg      greenBits = CHAN_BITS;
783848b8605Smrg      blueBits = CHAN_BITS;
784848b8605Smrg      alphaBits = 0;
785848b8605Smrg      rind = 0;
786848b8605Smrg      gind = 1;
787848b8605Smrg      bind = 2;
788848b8605Smrg   }
789848b8605Smrg   else if (format==OSMESA_BGR) {
790848b8605Smrg      redBits = CHAN_BITS;
791848b8605Smrg      greenBits = CHAN_BITS;
792848b8605Smrg      blueBits = CHAN_BITS;
793848b8605Smrg      alphaBits = 0;
794848b8605Smrg      rind = 2;
795848b8605Smrg      gind = 1;
796848b8605Smrg      bind = 0;
797848b8605Smrg   }
798848b8605Smrg#if CHAN_TYPE == GL_UNSIGNED_BYTE
799848b8605Smrg   else if (format==OSMESA_RGB_565) {
800848b8605Smrg      redBits = 5;
801848b8605Smrg      greenBits = 6;
802848b8605Smrg      blueBits = 5;
803848b8605Smrg      alphaBits = 0;
804848b8605Smrg      rind = 0; /* not used */
805848b8605Smrg      gind = 0;
806848b8605Smrg      bind = 0;
807848b8605Smrg   }
808848b8605Smrg#endif
809848b8605Smrg   else {
810848b8605Smrg      return NULL;
811848b8605Smrg   }
812848b8605Smrg
813848b8605Smrg   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
814848b8605Smrg   if (osmesa) {
815848b8605Smrg      osmesa->gl_visual = _mesa_create_visual( GL_FALSE,    /* double buffer */
816848b8605Smrg                                               GL_FALSE,    /* stereo */
817848b8605Smrg                                               redBits,
818848b8605Smrg                                               greenBits,
819848b8605Smrg                                               blueBits,
820848b8605Smrg                                               alphaBits,
821848b8605Smrg                                               depthBits,
822848b8605Smrg                                               stencilBits,
823848b8605Smrg                                               accumBits,
824848b8605Smrg                                               accumBits,
825848b8605Smrg                                               accumBits,
826848b8605Smrg                                               alphaBits ? accumBits : 0,
827848b8605Smrg                                               1            /* num samples */
828848b8605Smrg                                               );
829848b8605Smrg      if (!osmesa->gl_visual) {
830848b8605Smrg         free(osmesa);
831848b8605Smrg         return NULL;
832848b8605Smrg      }
833848b8605Smrg
834848b8605Smrg      /* Initialize device driver function table */
835848b8605Smrg      _mesa_init_driver_functions(&functions);
836b8e80941Smrg      _tnl_init_driver_draw_function(&functions);
837848b8605Smrg      /* override with our functions */
838848b8605Smrg      functions.GetString = get_string;
839b8e80941Smrg      functions.UpdateState = osmesa_update_state_wrapper;
840848b8605Smrg
841848b8605Smrg      if (!_mesa_initialize_context(&osmesa->mesa,
842b8e80941Smrg                                    api_profile,
843848b8605Smrg                                    osmesa->gl_visual,
844848b8605Smrg                                    sharelist ? &sharelist->mesa
845848b8605Smrg                                              : (struct gl_context *) NULL,
846848b8605Smrg                                    &functions)) {
847848b8605Smrg         _mesa_destroy_visual( osmesa->gl_visual );
848848b8605Smrg         free(osmesa);
849848b8605Smrg         return NULL;
850848b8605Smrg      }
851848b8605Smrg
852848b8605Smrg      _mesa_enable_sw_extensions(&(osmesa->mesa));
853848b8605Smrg
854848b8605Smrg      osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
855848b8605Smrg      if (!osmesa->gl_buffer) {
856848b8605Smrg         _mesa_destroy_visual( osmesa->gl_visual );
857b8e80941Smrg         _mesa_free_context_data(&osmesa->mesa, true);
858848b8605Smrg         free(osmesa);
859848b8605Smrg         return NULL;
860848b8605Smrg      }
861848b8605Smrg
862848b8605Smrg      /* Create depth/stencil/accum buffers.  We'll create the color
863848b8605Smrg       * buffer later in OSMesaMakeCurrent().
864848b8605Smrg       */
865848b8605Smrg      _swrast_add_soft_renderbuffers(osmesa->gl_buffer,
866848b8605Smrg                                     GL_FALSE, /* color */
867848b8605Smrg                                     osmesa->gl_visual->haveDepthBuffer,
868848b8605Smrg                                     osmesa->gl_visual->haveStencilBuffer,
869848b8605Smrg                                     osmesa->gl_visual->haveAccumBuffer,
870848b8605Smrg                                     GL_FALSE, /* alpha */
871848b8605Smrg                                     GL_FALSE /* aux */ );
872848b8605Smrg
873848b8605Smrg      osmesa->format = format;
874848b8605Smrg      osmesa->userRowLength = 0;
875848b8605Smrg      osmesa->yup = GL_TRUE;
876848b8605Smrg      osmesa->rInd = rind;
877848b8605Smrg      osmesa->gInd = gind;
878848b8605Smrg      osmesa->bInd = bind;
879848b8605Smrg      osmesa->aInd = aind;
880848b8605Smrg
881848b8605Smrg      _mesa_meta_init(&osmesa->mesa);
882848b8605Smrg
883848b8605Smrg      /* Initialize the software rasterizer and helper modules. */
884848b8605Smrg      {
885848b8605Smrg	 struct gl_context *ctx = &osmesa->mesa;
886848b8605Smrg         SWcontext *swrast;
887848b8605Smrg         TNLcontext *tnl;
888848b8605Smrg
889848b8605Smrg	 if (!_swrast_CreateContext( ctx ) ||
890848b8605Smrg             !_vbo_CreateContext( ctx ) ||
891848b8605Smrg             !_tnl_CreateContext( ctx ) ||
892848b8605Smrg             !_swsetup_CreateContext( ctx )) {
893848b8605Smrg            _mesa_destroy_visual(osmesa->gl_visual);
894b8e80941Smrg            _mesa_free_context_data(ctx, true);
895848b8605Smrg            free(osmesa);
896848b8605Smrg            return NULL;
897848b8605Smrg         }
898848b8605Smrg
899848b8605Smrg	 _swsetup_Wakeup( ctx );
900848b8605Smrg
901848b8605Smrg         /* use default TCL pipeline */
902848b8605Smrg         tnl = TNL_CONTEXT(ctx);
903848b8605Smrg         tnl->Driver.RunPipeline = _tnl_run_pipeline;
904848b8605Smrg
905848b8605Smrg         ctx->Driver.MapRenderbuffer = osmesa_MapRenderbuffer;
906848b8605Smrg         ctx->Driver.UnmapRenderbuffer = osmesa_UnmapRenderbuffer;
907848b8605Smrg
908848b8605Smrg         ctx->Driver.GenerateMipmap = _mesa_generate_mipmap;
909848b8605Smrg
910848b8605Smrg         /* Extend the software rasterizer with our optimized line and triangle
911848b8605Smrg          * drawing functions.
912848b8605Smrg          */
913848b8605Smrg         swrast = SWRAST_CONTEXT( ctx );
914848b8605Smrg         swrast->choose_line = osmesa_choose_line;
915848b8605Smrg         swrast->choose_triangle = osmesa_choose_triangle;
916848b8605Smrg
917b8e80941Smrg         _mesa_override_extensions(ctx);
918848b8605Smrg         _mesa_compute_version(ctx);
919848b8605Smrg
920b8e80941Smrg         if (ctx->Version < version_major * 10 + version_minor) {
921b8e80941Smrg            _mesa_destroy_visual(osmesa->gl_visual);
922b8e80941Smrg            _mesa_free_context_data(ctx, true);
923b8e80941Smrg            free(osmesa);
924b8e80941Smrg            return NULL;
925b8e80941Smrg         }
926b8e80941Smrg
927848b8605Smrg         /* Exec table initialization requires the version to be computed */
928848b8605Smrg         _mesa_initialize_dispatch_tables(ctx);
929848b8605Smrg         _mesa_initialize_vbo_vtxfmt(ctx);
930848b8605Smrg      }
931848b8605Smrg   }
932848b8605Smrg   return osmesa;
933848b8605Smrg}
934848b8605Smrg
935848b8605Smrg
936848b8605Smrg/**
937848b8605Smrg * Destroy an Off-Screen Mesa rendering context.
938848b8605Smrg *
939848b8605Smrg * \param osmesa  the context to destroy
940848b8605Smrg */
941848b8605SmrgGLAPI void GLAPIENTRY
942848b8605SmrgOSMesaDestroyContext( OSMesaContext osmesa )
943848b8605Smrg{
944848b8605Smrg   if (osmesa) {
945848b8605Smrg      if (osmesa->srb)
946848b8605Smrg         _mesa_reference_renderbuffer((struct gl_renderbuffer **) &osmesa->srb, NULL);
947848b8605Smrg
948848b8605Smrg      _mesa_meta_free( &osmesa->mesa );
949848b8605Smrg
950848b8605Smrg      _swsetup_DestroyContext( &osmesa->mesa );
951848b8605Smrg      _tnl_DestroyContext( &osmesa->mesa );
952848b8605Smrg      _vbo_DestroyContext( &osmesa->mesa );
953848b8605Smrg      _swrast_DestroyContext( &osmesa->mesa );
954848b8605Smrg
955848b8605Smrg      _mesa_destroy_visual( osmesa->gl_visual );
956848b8605Smrg      _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL );
957848b8605Smrg
958b8e80941Smrg      _mesa_free_context_data(&osmesa->mesa, true);
959848b8605Smrg      free( osmesa );
960848b8605Smrg   }
961848b8605Smrg}
962848b8605Smrg
963848b8605Smrg
964848b8605Smrg/**
965848b8605Smrg * Bind an OSMesaContext to an image buffer.  The image buffer is just a
966848b8605Smrg * block of memory which the client provides.  Its size must be at least
967848b8605Smrg * as large as width*height*sizeof(type).  Its address should be a multiple
968848b8605Smrg * of 4 if using RGBA mode.
969848b8605Smrg *
970848b8605Smrg * Image data is stored in the order of glDrawPixels:  row-major order
971848b8605Smrg * with the lower-left image pixel stored in the first array position
972848b8605Smrg * (ie. bottom-to-top).
973848b8605Smrg *
974848b8605Smrg * If the context's viewport hasn't been initialized yet, it will now be
975848b8605Smrg * initialized to (0,0,width,height).
976848b8605Smrg *
977b8e80941Smrg * If both the context and the buffer are null, the current context will be
978b8e80941Smrg * unbound.
979b8e80941Smrg *
980848b8605Smrg * Input:  osmesa - the rendering context
981848b8605Smrg *         buffer - the image buffer memory
982848b8605Smrg *         type - data type for pixel components
983848b8605Smrg *            Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
984848b8605Smrg *            are supported.  But if Mesa's been compiled with CHAN_BITS==16
985848b8605Smrg *            then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.  And if
986848b8605Smrg *            Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT,
987848b8605Smrg *            GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.
988848b8605Smrg *         width, height - size of image buffer in pixels, at least 1
989848b8605Smrg * Return:  GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
990848b8605Smrg *          invalid buffer address, invalid type, width<1, height<1,
991848b8605Smrg *          width>internal limit or height>internal limit.
992848b8605Smrg */
993848b8605SmrgGLAPI GLboolean GLAPIENTRY
994848b8605SmrgOSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type,
995848b8605Smrg                   GLsizei width, GLsizei height )
996848b8605Smrg{
997b8e80941Smrg   if (!osmesa && !buffer) {
998b8e80941Smrg      return _mesa_make_current(NULL, NULL, NULL);
999b8e80941Smrg   }
1000b8e80941Smrg
1001848b8605Smrg   if (!osmesa || !buffer ||
1002848b8605Smrg       width < 1 || height < 1 ||
1003848b8605Smrg       width > SWRAST_MAX_WIDTH || height > SWRAST_MAX_HEIGHT) {
1004848b8605Smrg      return GL_FALSE;
1005848b8605Smrg   }
1006848b8605Smrg
1007848b8605Smrg   if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
1008848b8605Smrg      return GL_FALSE;
1009848b8605Smrg   }
1010848b8605Smrg
1011848b8605Smrg#if 0
1012848b8605Smrg   if (!(type == GL_UNSIGNED_BYTE ||
1013848b8605Smrg         (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) ||
1014848b8605Smrg         (type == GL_FLOAT && CHAN_BITS == 32))) {
1015848b8605Smrg      /* i.e. is sizeof(type) * 8 > CHAN_BITS? */
1016848b8605Smrg      return GL_FALSE;
1017848b8605Smrg   }
1018848b8605Smrg#endif
1019848b8605Smrg
1020848b8605Smrg   osmesa_update_state( &osmesa->mesa, 0 );
1021848b8605Smrg
1022848b8605Smrg   /* Create a front/left color buffer which wraps the user-provided buffer.
1023848b8605Smrg    * There is no back color buffer.
1024848b8605Smrg    * If the user tries to use a 8, 16 or 32-bit/channel buffer that
1025848b8605Smrg    * doesn't match what Mesa was compiled for (CHAN_BITS) the
1026b8e80941Smrg    * _mesa_attach_and_reference_rb() function will create a "wrapper"
1027b8e80941Smrg    * renderbuffer that converts rendering from CHAN_BITS to the
1028b8e80941Smrg    * user-requested channel size.
1029848b8605Smrg    */
1030848b8605Smrg   if (!osmesa->srb) {
1031848b8605Smrg      osmesa->srb = new_osmesa_renderbuffer(&osmesa->mesa, osmesa->format, type);
1032848b8605Smrg      _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
1033b8e80941Smrg      _mesa_attach_and_reference_rb(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
1034b8e80941Smrg                                    &osmesa->srb->Base);
1035848b8605Smrg      assert(osmesa->srb->Base.RefCount == 2);
1036848b8605Smrg   }
1037848b8605Smrg
1038848b8605Smrg   osmesa->DataType = type;
1039848b8605Smrg
1040848b8605Smrg   /* Set renderbuffer fields.  Set width/height = 0 to force
1041848b8605Smrg    * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer()
1042848b8605Smrg    */
1043848b8605Smrg   osmesa->srb->Buffer = buffer;
1044848b8605Smrg   osmesa->srb->Base.Width = osmesa->srb->Base.Height = 0;
1045848b8605Smrg
1046848b8605Smrg   /* Set the framebuffer's size.  This causes the
1047848b8605Smrg    * osmesa_renderbuffer_storage() function to get called.
1048848b8605Smrg    */
1049848b8605Smrg   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
1050848b8605Smrg
1051848b8605Smrg   _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer );
1052848b8605Smrg
1053848b8605Smrg   /* Remove renderbuffer attachment, then re-add.  This installs the
1054848b8605Smrg    * renderbuffer adaptor/wrapper if needed (for bpp conversion).
1055848b8605Smrg    */
1056848b8605Smrg   _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
1057b8e80941Smrg   _mesa_attach_and_reference_rb(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
1058b8e80941Smrg                                 &osmesa->srb->Base);
1059848b8605Smrg
1060848b8605Smrg
1061848b8605Smrg   /* this updates the visual's red/green/blue/alphaBits fields */
1062848b8605Smrg   _mesa_update_framebuffer_visual(&osmesa->mesa, osmesa->gl_buffer);
1063848b8605Smrg
1064848b8605Smrg   /* update the framebuffer size */
1065848b8605Smrg   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
1066848b8605Smrg
1067848b8605Smrg   return GL_TRUE;
1068848b8605Smrg}
1069848b8605Smrg
1070848b8605Smrg
1071848b8605Smrg
1072848b8605SmrgGLAPI OSMesaContext GLAPIENTRY
1073848b8605SmrgOSMesaGetCurrentContext( void )
1074848b8605Smrg{
1075848b8605Smrg   struct gl_context *ctx = _mesa_get_current_context();
1076848b8605Smrg   if (ctx)
1077848b8605Smrg      return (OSMesaContext) ctx;
1078848b8605Smrg   else
1079848b8605Smrg      return NULL;
1080848b8605Smrg}
1081848b8605Smrg
1082848b8605Smrg
1083848b8605Smrg
1084848b8605SmrgGLAPI void GLAPIENTRY
1085848b8605SmrgOSMesaPixelStore( GLint pname, GLint value )
1086848b8605Smrg{
1087848b8605Smrg   OSMesaContext osmesa = OSMesaGetCurrentContext();
1088848b8605Smrg
1089848b8605Smrg   switch (pname) {
1090848b8605Smrg      case OSMESA_ROW_LENGTH:
1091848b8605Smrg         if (value<0) {
1092848b8605Smrg            _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
1093848b8605Smrg                      "OSMesaPixelStore(value)" );
1094848b8605Smrg            return;
1095848b8605Smrg         }
1096848b8605Smrg         osmesa->userRowLength = value;
1097848b8605Smrg         break;
1098848b8605Smrg      case OSMESA_Y_UP:
1099848b8605Smrg         osmesa->yup = value ? GL_TRUE : GL_FALSE;
1100848b8605Smrg         break;
1101848b8605Smrg      default:
1102848b8605Smrg         _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
1103848b8605Smrg         return;
1104848b8605Smrg   }
1105848b8605Smrg
1106848b8605Smrg   compute_row_addresses( osmesa );
1107848b8605Smrg}
1108848b8605Smrg
1109848b8605Smrg
1110848b8605SmrgGLAPI void GLAPIENTRY
1111848b8605SmrgOSMesaGetIntegerv( GLint pname, GLint *value )
1112848b8605Smrg{
1113848b8605Smrg   OSMesaContext osmesa = OSMesaGetCurrentContext();
1114848b8605Smrg
1115848b8605Smrg   switch (pname) {
1116848b8605Smrg      case OSMESA_WIDTH:
1117848b8605Smrg         if (osmesa->gl_buffer)
1118848b8605Smrg            *value = osmesa->gl_buffer->Width;
1119848b8605Smrg         else
1120848b8605Smrg            *value = 0;
1121848b8605Smrg         return;
1122848b8605Smrg      case OSMESA_HEIGHT:
1123848b8605Smrg         if (osmesa->gl_buffer)
1124848b8605Smrg            *value = osmesa->gl_buffer->Height;
1125848b8605Smrg         else
1126848b8605Smrg            *value = 0;
1127848b8605Smrg         return;
1128848b8605Smrg      case OSMESA_FORMAT:
1129848b8605Smrg         *value = osmesa->format;
1130848b8605Smrg         return;
1131848b8605Smrg      case OSMESA_TYPE:
1132848b8605Smrg         /* current color buffer's data type */
1133848b8605Smrg         *value = osmesa->DataType;
1134848b8605Smrg         return;
1135848b8605Smrg      case OSMESA_ROW_LENGTH:
1136848b8605Smrg         *value = osmesa->userRowLength;
1137848b8605Smrg         return;
1138848b8605Smrg      case OSMESA_Y_UP:
1139848b8605Smrg         *value = osmesa->yup;
1140848b8605Smrg         return;
1141848b8605Smrg      case OSMESA_MAX_WIDTH:
1142848b8605Smrg         *value = SWRAST_MAX_WIDTH;
1143848b8605Smrg         return;
1144848b8605Smrg      case OSMESA_MAX_HEIGHT:
1145848b8605Smrg         *value = SWRAST_MAX_HEIGHT;
1146848b8605Smrg         return;
1147848b8605Smrg      default:
1148848b8605Smrg         _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1149848b8605Smrg         return;
1150848b8605Smrg   }
1151848b8605Smrg}
1152848b8605Smrg
1153848b8605Smrg
1154848b8605Smrg/**
1155848b8605Smrg * Return the depth buffer associated with an OSMesa context.
1156848b8605Smrg * Input:  c - the OSMesa context
1157848b8605Smrg * Output:  width, height - size of buffer in pixels
1158848b8605Smrg *          bytesPerValue - bytes per depth value (2 or 4)
1159848b8605Smrg *          buffer - pointer to depth buffer values
1160848b8605Smrg * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1161848b8605Smrg */
1162848b8605SmrgGLAPI GLboolean GLAPIENTRY
1163848b8605SmrgOSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1164848b8605Smrg                      GLint *bytesPerValue, void **buffer )
1165848b8605Smrg{
1166848b8605Smrg   struct swrast_renderbuffer *srb = NULL;
1167848b8605Smrg
1168848b8605Smrg   if (c->gl_buffer)
1169848b8605Smrg      srb = swrast_renderbuffer(c->gl_buffer->
1170848b8605Smrg                                Attachment[BUFFER_DEPTH].Renderbuffer);
1171848b8605Smrg
1172848b8605Smrg   if (!srb || !srb->Buffer) {
1173848b8605Smrg      *width = 0;
1174848b8605Smrg      *height = 0;
1175848b8605Smrg      *bytesPerValue = 0;
1176848b8605Smrg      *buffer = 0;
1177848b8605Smrg      return GL_FALSE;
1178848b8605Smrg   }
1179848b8605Smrg   else {
1180848b8605Smrg      *width = srb->Base.Width;
1181848b8605Smrg      *height = srb->Base.Height;
1182848b8605Smrg      if (c->gl_visual->depthBits <= 16)
1183848b8605Smrg         *bytesPerValue = sizeof(GLushort);
1184848b8605Smrg      else
1185848b8605Smrg         *bytesPerValue = sizeof(GLuint);
1186848b8605Smrg      *buffer = (void *) srb->Buffer;
1187848b8605Smrg      return GL_TRUE;
1188848b8605Smrg   }
1189848b8605Smrg}
1190848b8605Smrg
1191848b8605Smrg
1192848b8605Smrg/**
1193848b8605Smrg * Return the color buffer associated with an OSMesa context.
1194848b8605Smrg * Input:  c - the OSMesa context
1195848b8605Smrg * Output:  width, height - size of buffer in pixels
1196848b8605Smrg *          format - the pixel format (OSMESA_FORMAT)
1197848b8605Smrg *          buffer - pointer to color buffer values
1198848b8605Smrg * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1199848b8605Smrg */
1200848b8605SmrgGLAPI GLboolean GLAPIENTRY
1201848b8605SmrgOSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width,
1202848b8605Smrg                      GLint *height, GLint *format, void **buffer )
1203848b8605Smrg{
1204848b8605Smrg   if (osmesa->srb && osmesa->srb->Buffer) {
1205848b8605Smrg      *width = osmesa->srb->Base.Width;
1206848b8605Smrg      *height = osmesa->srb->Base.Height;
1207848b8605Smrg      *format = osmesa->format;
1208848b8605Smrg      *buffer = (void *) osmesa->srb->Buffer;
1209848b8605Smrg      return GL_TRUE;
1210848b8605Smrg   }
1211848b8605Smrg   else {
1212848b8605Smrg      *width = 0;
1213848b8605Smrg      *height = 0;
1214848b8605Smrg      *format = 0;
1215848b8605Smrg      *buffer = 0;
1216848b8605Smrg      return GL_FALSE;
1217848b8605Smrg   }
1218848b8605Smrg}
1219848b8605Smrg
1220848b8605Smrg
1221848b8605Smrgstruct name_function
1222848b8605Smrg{
1223848b8605Smrg   const char *Name;
1224848b8605Smrg   OSMESAproc Function;
1225848b8605Smrg};
1226848b8605Smrg
1227848b8605Smrgstatic struct name_function functions[] = {
1228848b8605Smrg   { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
1229848b8605Smrg   { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
1230b8e80941Smrg   { "OSMesaCreateContextAttribs", (OSMESAproc) OSMesaCreateContextAttribs },
1231848b8605Smrg   { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
1232848b8605Smrg   { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
1233848b8605Smrg   { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
1234b8e80941Smrg   { "OSMesaPixelStore", (OSMESAproc) OSMesaPixelStore },
1235848b8605Smrg   { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
1236848b8605Smrg   { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1237848b8605Smrg   { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1238848b8605Smrg   { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1239848b8605Smrg   { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
1240848b8605Smrg   { "OSMesaPostprocess", (OSMESAproc) OSMesaPostprocess },
1241848b8605Smrg   { NULL, NULL }
1242848b8605Smrg};
1243848b8605Smrg
1244848b8605Smrg
1245848b8605SmrgGLAPI OSMESAproc GLAPIENTRY
1246848b8605SmrgOSMesaGetProcAddress( const char *funcName )
1247848b8605Smrg{
1248848b8605Smrg   int i;
1249848b8605Smrg   for (i = 0; functions[i].Name; i++) {
1250848b8605Smrg      if (strcmp(functions[i].Name, funcName) == 0)
1251848b8605Smrg         return functions[i].Function;
1252848b8605Smrg   }
1253848b8605Smrg   return _glapi_get_proc_address(funcName);
1254848b8605Smrg}
1255848b8605Smrg
1256848b8605Smrg
1257848b8605SmrgGLAPI void GLAPIENTRY
1258848b8605SmrgOSMesaColorClamp(GLboolean enable)
1259848b8605Smrg{
1260848b8605Smrg   OSMesaContext osmesa = OSMesaGetCurrentContext();
1261848b8605Smrg
1262848b8605Smrg   if (enable == GL_TRUE) {
1263848b8605Smrg      osmesa->mesa.Color.ClampFragmentColor = GL_TRUE;
1264848b8605Smrg   }
1265848b8605Smrg   else {
1266848b8605Smrg      osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
1267848b8605Smrg   }
1268848b8605Smrg}
1269848b8605Smrg
1270848b8605Smrg
1271848b8605SmrgGLAPI void GLAPIENTRY
1272848b8605SmrgOSMesaPostprocess(OSMesaContext osmesa, const char *filter,
1273848b8605Smrg                  unsigned enable_value)
1274848b8605Smrg{
1275848b8605Smrg   fprintf(stderr,
1276848b8605Smrg           "OSMesaPostProcess() is only available with gallium drivers\n");
1277848b8605Smrg}
1278848b8605Smrg
1279848b8605Smrg
1280848b8605Smrg
1281848b8605Smrg/**
1282848b8605Smrg * When GLX_INDIRECT_RENDERING is defined, some symbols are missing in
1283848b8605Smrg * libglapi.a.  We need to define them here.
1284848b8605Smrg */
1285848b8605Smrg#ifdef GLX_INDIRECT_RENDERING
1286848b8605Smrg
1287848b8605Smrg#define GL_GLEXT_PROTOTYPES
1288848b8605Smrg#include "GL/gl.h"
1289848b8605Smrg#include "glapi/glapi.h"
1290b8e80941Smrg#include "glapitable.h"
1291848b8605Smrg
1292848b8605Smrg#if defined(USE_MGL_NAMESPACE)
1293848b8605Smrg#define NAME(func)  mgl##func
1294848b8605Smrg#else
1295848b8605Smrg#define NAME(func)  gl##func
1296848b8605Smrg#endif
1297848b8605Smrg
1298848b8605Smrg#define DISPATCH(FUNC, ARGS, MESSAGE)		\
1299848b8605Smrg   GET_DISPATCH()->FUNC ARGS
1300848b8605Smrg
1301848b8605Smrg#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) 	\
1302848b8605Smrg   return GET_DISPATCH()->FUNC ARGS
1303848b8605Smrg
1304848b8605Smrg/* skip normal ones */
1305848b8605Smrg#define _GLAPI_SKIP_NORMAL_ENTRY_POINTS
1306b8e80941Smrg#include "glapitemp.h"
1307848b8605Smrg
1308848b8605Smrg#endif /* GLX_INDIRECT_RENDERING */
1309