1 /*
2  * This the Mesa driver for Allegro 4.0
3  * It is based on the work of Bernhard Tsirren
4  */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #define GL_GLEXT_PROTOTYPES
9 #include "GL/gl.h"
10 #include "GL/glext.h"
11 #include "GL/amesa.h"
12 #include "raster.h"
13 
14 
15 typedef struct _amesa_extension_data {
16 	void* proc;
17 	char* name;
18 } amesa_extension_data;
19 
20 amesa_extension_data amesa_extension[] = {
21 #ifdef GL_EXT_polygon_offset
22    { (void*)glPolygonOffsetEXT,			"glPolygonOffsetEXT"		},
23 #endif
24    { (void*)glBlendEquationEXT,			"glBlendEquationEXT"		},
25    { (void*)glBlendColorEXT,			"glBlendColorExt"		},
26    { (void*)glVertexPointerEXT,			"glVertexPointerEXT"		},
27    { (void*)glNormalPointerEXT,			"glNormalPointerEXT"		},
28    { (void*)glColorPointerEXT,			"glColorPointerEXT"		},
29    { (void*)glIndexPointerEXT,			"glIndexPointerEXT"		},
30    { (void*)glTexCoordPointerEXT,		"glTexCoordPointer"		},
31    { (void*)glEdgeFlagPointerEXT,		"glEdgeFlagPointerEXT"		},
32    { (void*)glGetPointervEXT,			"glGetPointervEXT"		},
33    { (void*)glArrayElementEXT,			"glArrayElementEXT"		},
34    { (void*)glDrawArraysEXT,			"glDrawArrayEXT"		},
35    { (void*)glAreTexturesResidentEXT,		"glAreTexturesResidentEXT"	},
36    { (void*)glBindTextureEXT,			"glBindTextureEXT"		},
37    { (void*)glDeleteTexturesEXT,		"glDeleteTexturesEXT"		},
38    { (void*)glGenTexturesEXT,			"glGenTexturesEXT"		},
39    { (void*)glIsTextureEXT,			"glIsTextureEXT"		},
40    { (void*)glPrioritizeTexturesEXT,		"glPrioritizeTexturesEXT"	},
41    { (void*)glCopyTexSubImage3DEXT,		"glCopyTexSubImage3DEXT"	},
42    { (void*)glTexImage3DEXT,			"glTexImage3DEXT"		},
43    { (void*)glTexSubImage3DEXT,			"glTexSubImage3DEXT"		},
44    { (void*)glColorTableEXT,			"glColorTableEXT"		},
45    { (void*)glColorSubTableEXT,			"glColorSubTableEXT"		},
46    { (void*)glGetColorTableEXT,			"glGetColorTableEXT"		},
47    { (void*)glGetColorTableParameterfvEXT,	"glGetColorTableParameterfvEXT"	},
48    { (void*)glGetColorTableParameterivEXT,	"glGetColorTableParameterivEXT"	},
49    { (void*)glPointParameterfEXT,		"glPointParameterfEXT"		},
50    { (void*)glPointParameterfvEXT,		"glPointParameterfvEXT"		},
51    { (void*)glBlendFuncSeparateEXT,		"glBlendFuncSeparateEXT"	},
52    { (void*)glLockArraysEXT,			"glLockArraysEXT"		},
53    { (void*)glUnlockArraysEXT,			"glUnlockArraysEXT"		},
54    { NULL,					'\0'				}
55 };
56 
57 #define AMESA_NEW_LINE   (_NEW_LINE | \
58                            _NEW_TEXTURE | \
59                            _NEW_LIGHT | \
60                            _NEW_DEPTH | \
61                            _NEW_RENDERMODE | \
62                            _SWRAST_NEW_RASTERMASK)
63 
64 #define AMESA_NEW_TRIANGLE (_NEW_POLYGON | \
65                              _NEW_TEXTURE | \
66                              _NEW_LIGHT | \
67                              _NEW_DEPTH | \
68                              _NEW_RENDERMODE | \
69                              _SWRAST_NEW_RASTERMASK)
70 
71 AMesaContext AMesa = NULL;    /* the current context */
72 
73 /**********************************************************************/
74 /*****                AMesa Public API Functions                  *****/
75 /**********************************************************************/
76 
77 AMesaVisual GLAPIENTRY
AMesaCreateVisual(GLboolean dbFlag,GLint depth,GLint rgba,GLint depthSize,GLint stencilSize,GLint accumSizeRed,GLint accumSizeGreen,GLint accumSizeBlue,GLint accumSizeAlpha)78 AMesaCreateVisual(GLboolean dbFlag, GLint depth, GLint rgba,
79                   GLint depthSize, GLint stencilSize, GLint accumSizeRed,
80 		  GLint accumSizeGreen, GLint accumSizeBlue, GLint accumSizeAlpha)
81 {
82 	AMesaVisual visual;
83 	GLbyte redBits, greenBits, blueBits, alphaBits, indexBits;
84 
85 	if ((!rgba) && (depthSize != 8))
86 		return NULL;
87 
88 	visual = (AMesaVisual) malloc(sizeof(struct amesa_visual));
89 	if (!visual)
90 		return NULL;
91 
92 	switch (depth) {
93 
94 		case 8:
95 			if (rgba) {
96 				redBits   = 3;
97 				greenBits = 3;
98 				blueBits  = 2;
99 				alphaBits = 0;
100 				indexBits = 0;
101 			}
102 			else {
103 				redBits   = 0;
104 				greenBits = 0;
105 				blueBits  = 0;
106 				alphaBits = 0;
107 				indexBits = 8;
108 			}
109 			break;
110 
111 		case 15:
112 			redBits   = 5;
113 			greenBits = 5;
114 			blueBits  = 5;
115 			alphaBits = 0;
116 			indexBits = 0;
117 			break;
118 
119 		case 16:
120 			redBits   = 5;
121 			greenBits = 6;
122 			blueBits  = 5;
123 			alphaBits = 0;
124 			indexBits = 0;
125 			break;
126 
127 		case 24:
128 			redBits   = 8;
129 			greenBits = 8;
130 			blueBits  = 8;
131 			alphaBits = 0;
132 			indexBits = 0;
133 			break;
134 
135 		case 32:
136 			redBits   = 8;
137 			greenBits = 8;
138 			blueBits  = 8;
139 			alphaBits = 8;
140 			indexBits = 0;
141 		break;
142 
143 		default:
144 			free(visual);
145 			return NULL;
146 	}
147 
148 	if (depthSize)
149 		depthSize = 16;
150 
151 	visual->DBFlag = dbFlag;
152 	visual->Depth = depth;
153 	visual->GLVisual = _mesa_create_visual(rgba,    /* rgb mode       */
154    					dbFlag,		/* double buffer */
155 					GL_FALSE,	/* stereo*/
156 					redBits,
157 					greenBits,
158 					blueBits,
159 					alphaBits,
160 					indexBits,
161 					depthSize,
162 					stencilSize,
163 					accumSizeBlue,
164 					accumSizeRed,
165 					accumSizeGreen,
166 					alphaBits ? accumSizeAlpha : 0,
167 					1);
168 	if (!visual->GLVisual) {
169 		free(visual);
170 		return NULL;
171 	}
172 
173 	return visual;
174 }
175 
176 
177 
AMesaDestroyVisual(AMesaVisual visual)178 void GLAPIENTRY AMesaDestroyVisual(AMesaVisual visual)
179 {
180 	_mesa_destroy_visual(visual->GLVisual);
181 	free(visual);
182 }
183 
184 
185 
AMesaCreateBuffer(AMesaVisual visual,BITMAP * bmp)186 AMesaBuffer GLAPIENTRY AMesaCreateBuffer(AMesaVisual visual, BITMAP* bmp)
187 {
188 	AMesaBuffer buffer;
189 
190 	/* Buffer and visual must share the same color depth */
191 	if (bitmap_color_depth(bmp) != visual->Depth)
192 		return NULL;
193 
194 	buffer = (AMesaBuffer) malloc(sizeof(struct amesa_buffer));
195 	if (!buffer)
196 		return NULL;
197 
198 	buffer->FrontBuffer    = bmp;
199 	buffer->BackBuffer     = NULL;
200 	buffer->Active         = NULL;
201 	buffer->ReadActive     = NULL;
202 	buffer->DepthBuffer    = NULL;
203 
204 	if (visual->DBFlag) {
205 		buffer->BackBuffer = create_bitmap_ex(visual->Depth, bmp->w, bmp->h);
206 		if (!buffer->BackBuffer) {
207 			free(buffer);
208 			return NULL;
209 		}
210 	}
211 
212 	if (visual->GLVisual->depthBits > 0) {
213 		buffer->DepthBuffer = create_zbuffer(bmp);
214 		if (!buffer->DepthBuffer) {
215 			if (buffer->BackBuffer)
216 				destroy_bitmap(buffer->BackBuffer);
217 			free(buffer);
218 			return NULL;
219 		}
220 		set_zbuffer(buffer->DepthBuffer);
221 	}
222 
223 	buffer->GLBuffer = _mesa_create_framebuffer(visual->GLVisual,
224                          0,   				    /*depth buffer is handled by Allegro */
225                          visual->GLVisual->stencilBits > 0, /*software stencil buffer*/
226                          visual->GLVisual->accumRedBits > 0,/*software accum buffer*/
227                          GL_FALSE ); /*software alpha buffer*/
228 
229 	if (!buffer->GLBuffer) {
230 		if (buffer->BackBuffer)
231 			destroy_bitmap(buffer->BackBuffer);
232 		if (buffer->DepthBuffer)
233 			destroy_zbuffer(buffer->DepthBuffer);
234 		free(buffer);
235       		return NULL;
236 	}
237 
238 	buffer->Width  = bmp->w;
239 	buffer->Height = bmp->h;
240 
241 	return buffer;
242 }
243 
244 
245 
AMesaDestroyBuffer(AMesaBuffer buffer)246 void GLAPIENTRY AMesaDestroyBuffer(AMesaBuffer buffer)
247 {
248 	if (buffer->BackBuffer)
249 		destroy_bitmap(buffer->BackBuffer);
250 	if (buffer->DepthBuffer)
251 		destroy_zbuffer(buffer->DepthBuffer);
252 
253 	_mesa_destroy_framebuffer(buffer->GLBuffer);
254 	free(buffer);
255 }
256 
257 
258 
259 /* Extend the software rasterizer with our line and triangle
260  * functions.
261  */
AMesaRegisterSwrastFunctions(GLcontext * ctx)262 static void AMesaRegisterSwrastFunctions( GLcontext *ctx )
263 {
264    SWcontext *swrast = SWRAST_CONTEXT( ctx );
265 
266    swrast->choose_line = AMesaChooseLine;
267    swrast->choose_triangle = AMesaChooseTriangle;
268 
269    swrast->invalidate_line |= AMESA_NEW_LINE;
270    swrast->invalidate_triangle |= AMESA_NEW_TRIANGLE;
271 }
272 
273 
274 
AMesaCreateContext(AMesaVisual visual,AMesaContext share)275 AMesaContext GLAPIENTRY AMesaCreateContext(AMesaVisual visual, AMesaContext share)
276 {
277 	AMesaContext context;
278 	GLboolean direct = GL_FALSE;
279 	GLcontext *ctx;
280 
281 	context = (AMesaContext) malloc(sizeof(struct amesa_context));
282 	if (!context)
283 		return NULL;
284 
285 	context->GLContext = _mesa_create_context(visual->GLVisual,
286                                              share ? share->GLContext : NULL,
287                                              (void*)context,
288                                              direct);
289 	if (!context->GLContext) {
290 		free(context);
291 		return NULL;
292 	}
293 
294 	context->Visual = visual;
295 
296 	ctx = context->GLContext;
297 	_mesa_enable_sw_extensions(ctx);
298 	_mesa_enable_1_3_extensions(ctx);
299 
300 	/* Initialize the software rasterizer and helper modules. */
301 
302 	_swrast_CreateContext( ctx );
303 	_ac_CreateContext( ctx );
304 	_tnl_CreateContext( ctx );
305 	_swsetup_CreateContext( ctx );
306 
307 	_swsetup_Wakeup( ctx );
308 	/*AMesaRegisterSwrastFunctions(ctx);*/
309 
310 	return context;
311 }
312 
313 
314 
AMesaDestroyContext(AMesaContext context)315 void GLAPIENTRY AMesaDestroyContext(AMesaContext context)
316 {
317 	if (context) {
318 		_swsetup_DestroyContext(context->GLContext);
319 		_tnl_DestroyContext(context->GLContext);
320 		_ac_DestroyContext(context->GLContext);
321 		_swrast_DestroyContext(context->GLContext);
322 
323 		_mesa_free_context_data(context->GLContext);
324 		free(context);
325 	}
326 }
327 
328 
329 
330 /*
331  * Make the specified context and buffer the current one.
332  */
AMesaMakeCurrent(AMesaContext context,AMesaBuffer buffer)333 GLboolean GLAPIENTRY AMesaMakeCurrent(AMesaContext context, AMesaBuffer buffer)
334 {
335 	if (context && buffer) {
336 		context->Buffer = buffer;
337 		buffer->Active  = buffer->BackBuffer ? buffer->BackBuffer : buffer->FrontBuffer;
338 		buffer->ReadActive = buffer->Active;
339 		context->ClearDepth =  2 << context->Visual->GLVisual->depthBits;
340 		context->zNear = 0.;
341 		context->zFar = 1.;
342 		context->ClearColor = 0;
343 		context->ClearIndex = 0;
344 		context->ColorIndex = 0;
345 
346 		AMesaUpdateState(context->GLContext, ~0);
347 		_mesa_make_current(context->GLContext, buffer->GLBuffer);
348 		if (context->GLContext->Viewport.Width == 0 ||
349 		    context->GLContext->Viewport.Height == 0) {
350 			/* initialize viewport and scissor box to buffer size */
351 			_mesa_Viewport(0, 0, buffer->Width, buffer->Height);
352 			context->GLContext->Scissor.Width = buffer->Width;
353 			context->GLContext->Scissor.Height = buffer->Height;
354 		}
355 		AMesa = context;
356 	}
357 	else {
358 		if (context) {
359 			/* Detach */
360 			context->Buffer->Active = NULL;
361 			context->Buffer->ReadActive = NULL;
362 			context->Buffer = NULL;
363 			_mesa_make_current(NULL, NULL);
364 			AMesa = NULL;
365 		}
366 		else
367 			return GL_FALSE;
368 	}
369 
370 	return GL_TRUE;
371 }
372 
373 
374 
AMesaSwapBuffers(AMesaBuffer buffer)375 void GLAPIENTRY AMesaSwapBuffers(AMesaBuffer buffer)
376 {
377 	if (buffer->BackBuffer)
378 		blit(buffer->BackBuffer, buffer->FrontBuffer,
379 		0, 0, 0, 0, buffer->Width, buffer->Height);
380 }
381 
382 
383 
AMesaGetCurrentContext(void)384 AMesaContext GLAPIENTRY AMesaGetCurrentContext (void)
385 {
386 	return AMesa;
387 }
388 
389 
390 
AMesaGetColorBuffer(AMesaBuffer buffer,GLenum mode)391 BITMAP* GLAPIENTRY AMesaGetColorBuffer(AMesaBuffer buffer, GLenum mode)
392 {
393 	switch (mode) {
394 		case AMESA_FRONT:
395 			return buffer->FrontBuffer;
396 
397 		case AMESA_BACK:
398 			if (buffer->BackBuffer)
399 				return buffer->BackBuffer;
400 			else
401 				return NULL;
402 
403 		case AMESA_ACTIVE:
404 			return buffer->Active;
405 
406 		default:
407 			return NULL;
408 	}
409 }
410 
AMesaGetProcAddress(AL_CONST char * name)411 void* GLAPIENTRY AMesaGetProcAddress(AL_CONST char *name)
412 {
413 	int i = 0;
414 
415 	while (amesa_extension[i].proc) {
416 		if (ustrcmp(amesa_extension[i].name, name) == 0)
417 			return amesa_extension[i].proc;
418 		i++;
419 	}
420 
421 	return NULL;
422 }
423