518211ccf467431bae4131ea82e39f926436b660
[mesa.git] / src / mesa / drivers / allegro / amesa.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 3.0
4 * Copyright (C) 1995-1998 Brian Paul
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <allegro.h>
24 #include "buffers.h"
25 #include "context.h"
26 #include "imports.h"
27 #include "matrix.h"
28 #include "mtypes.h"
29 #include "GL/amesa.h"
30
31
32 struct amesa_visual
33 {
34 GLvisual *GLVisual; /* inherit from GLvisual */
35 GLboolean DBFlag; /* double buffered? */
36 GLuint Depth; /* bits per pixel ( >= 15 ) */
37 };
38
39
40 struct amesa_buffer
41 {
42 GLframebuffer *GLBuffer; /* inherit from GLframebuffer */
43 GLuint Width, Height;
44 BITMAP *Screen;
45 BITMAP *Background;
46 BITMAP *Active;
47 };
48
49
50 struct amesa_context
51 {
52 GLcontext *GLContext; /* inherit from GLcontext */
53 AMesaVisual Visual;
54 AMesaBuffer Buffer;
55 GLuint ClearColor;
56 GLuint CurrentColor;
57 };
58
59
60 static void setup_dd_pointers(GLcontext *ctx);
61
62
63 /**********************************************************************/
64 /***** drawing functions *****/
65 /**********************************************************************/
66
67 #define FLIP(context, y) (context->Buffer->Height - (y) - 1)
68
69 #include "allegro/generic.h"
70 #include "allegro/direct.h"
71
72
73 /**********************************************************************/
74 /***** 15-bit accelerated drawing funcs *****/
75 /**********************************************************************/
76
77 IMPLEMENT_WRITE_RGBA_SPAN(15, unsigned short)
78 IMPLEMENT_WRITE_RGB_SPAN(15, unsigned short)
79 IMPLEMENT_WRITE_MONO_RGBA_SPAN(15, unsigned short)
80 IMPLEMENT_READ_RGBA_SPAN(15, unsigned short)
81 IMPLEMENT_WRITE_RGBA_PIXELS(15, unsigned short)
82 IMPLEMENT_WRITE_MONO_RGBA_PIXELS(15, unsigned short)
83 IMPLEMENT_READ_RGBA_PIXELS(15, unsigned short)
84
85
86 /**********************************************************************/
87 /***** 16-bit accelerated drawing funcs *****/
88 /**********************************************************************/
89
90 IMPLEMENT_WRITE_RGBA_SPAN(16, unsigned short)
91 IMPLEMENT_WRITE_RGB_SPAN(16, unsigned short)
92 IMPLEMENT_WRITE_MONO_RGBA_SPAN(16, unsigned short)
93 IMPLEMENT_READ_RGBA_SPAN(16, unsigned short)
94 IMPLEMENT_WRITE_RGBA_PIXELS(16, unsigned short)
95 IMPLEMENT_WRITE_MONO_RGBA_PIXELS(16, unsigned short)
96 IMPLEMENT_READ_RGBA_PIXELS(16, unsigned short)
97
98
99 /**********************************************************************/
100 /***** 32-bit accelerated drawing funcs *****/
101 /**********************************************************************/
102
103 IMPLEMENT_WRITE_RGBA_SPAN(32, unsigned long)
104 IMPLEMENT_WRITE_RGB_SPAN(32, unsigned long)
105 IMPLEMENT_WRITE_MONO_RGBA_SPAN(32, unsigned long)
106 IMPLEMENT_READ_RGBA_SPAN(32, unsigned long)
107 IMPLEMENT_WRITE_RGBA_PIXELS(32, unsigned long)
108 IMPLEMENT_WRITE_MONO_RGBA_PIXELS(32, unsigned long)
109 IMPLEMENT_READ_RGBA_PIXELS(32, unsigned long)
110
111
112 /**********************************************************************/
113 /***** Miscellaneous device driver funcs *****/
114 /**********************************************************************/
115
116 static GLboolean set_buffer(GLcontext *ctx, GLframebuffer *buffer, GLuint bit)
117 {
118 AMesaContext context = (AMesaContext)(ctx->DriverCtx);
119 GLboolean ok = GL_TRUE;
120
121 if (bit == DD_FRONT_LEFT_BIT)
122 context->Buffer->Active = context->Buffer->Screen;
123
124 else if (bit == DD_BACK_LEFT)
125 {
126 if (context->Buffer->Background)
127 context->Buffer->Active = context->Buffer->Background;
128 else
129 ok = GL_FALSE;
130 }
131
132 else
133 ok = GL_FALSE;
134
135 return ok;
136 }
137
138
139 static void get_buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
140 {
141 AMesaContext context = (AMesaContext)(ctx->DriverCtx);
142
143 *width = context->Buffer->Width;
144 *height = context->Buffer->Height;
145 }
146
147
148 /**
149 * We only implement this function as a mechanism to check if the
150 * framebuffer size has changed (and update corresponding state).
151 */
152 static void viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
153 {
154 /* poll for window size change and realloc software Z/stencil/etc if needed */
155 GLuint newWidth, newHeight;
156 GLframebuffer *buffer = ctx->WinSysDrawBuffer;
157 get_buffer_size( &newWidth, &newHeight );
158 if (buffer->Width != newWidth || buffer->Height != newHeight) {
159 _mesa_resize_framebuffer(ctx, buffer, newWidth, newHeight );
160 }
161
162 }
163
164
165 /**********************************************************************/
166 /**********************************************************************/
167
168 static void setup_dd_pointers(GLcontext *ctx)
169 {
170 AMesaContext context = (AMesaContext)(ctx->DriverCtx);
171
172 /* Initialize all the pointers in the driver struct. Do this whenever */
173 /* a new context is made current or we change buffers via set_buffer! */
174
175 ctx->Driver.UpdateState = setup_dd_pointers;
176 ctx->Driver.SetBuffer = set_buffer;
177 ctx->Driver.GetBufferSize = get_buffer_size;
178 ctx->Driver.Viewport = viewport;
179
180 ctx->Driver.Color = set_color_generic;
181 ctx->Driver.ClearColor = clear_color_generic;
182 ctx->Driver.Clear = clear_generic;
183 ctx->Driver.WriteRGBASpan = write_rgba_span_generic;
184 ctx->Driver.WriteRGBSpan = write_rgb_span_generic;
185 ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_generic;
186 ctx->Driver.WriteRGBAPixels = write_rgba_pixels_generic;
187 ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_generic;
188 ctx->Driver.ReadRGBASpan = read_rgba_span_generic;
189 ctx->Driver.ReadRGBAPixels = read_rgba_pixels_generic;
190
191 if (context->Buffer->Active != screen)
192 {
193 switch (context->Visual->Depth)
194 {
195 case 15:
196 ctx->Driver.WriteRGBASpan = write_rgba_span_15;
197 ctx->Driver.WriteRGBSpan = write_rgb_span_15;
198 ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_15;
199 ctx->Driver.WriteRGBAPixels = write_rgba_pixels_15;
200 ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_15;
201 ctx->Driver.ReadRGBASpan = read_rgba_span_15;
202 ctx->Driver.ReadRGBAPixels = read_rgba_pixels_15;
203 break;
204
205 case 16:
206 ctx->Driver.WriteRGBASpan = write_rgba_span_16;
207 ctx->Driver.WriteRGBSpan = write_rgb_span_16;
208 ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_16;
209 ctx->Driver.WriteRGBAPixels = write_rgba_pixels_16;
210 ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_16;
211 ctx->Driver.ReadRGBASpan = read_rgba_span_16;
212 ctx->Driver.ReadRGBAPixels = read_rgba_pixels_16;
213 break;
214
215 case 32:
216 ctx->Driver.WriteRGBASpan = write_rgba_span_32;
217 ctx->Driver.WriteRGBSpan = write_rgb_span_32;
218 ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_32;
219 ctx->Driver.WriteRGBAPixels = write_rgba_pixels_32;
220 ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_32;
221 ctx->Driver.ReadRGBASpan = read_rgba_span_32;
222 ctx->Driver.ReadRGBAPixels = read_rgba_pixels_32;
223 break;
224 }
225 }
226 }
227
228
229 /**********************************************************************/
230 /***** AMesa Public API Functions *****/
231 /**********************************************************************/
232
233
234 AMesaVisual AMesaCreateVisual(GLboolean dbFlag, GLint depth,
235 GLint depthSize, GLint stencilSize, GLint accumSize)
236 {
237 AMesaVisual visual;
238 GLbyte redBits, greenBits, blueBits;
239
240 visual = (AMesaVisual)calloc(1, sizeof(struct amesa_visual));
241 if (!visual)
242 return NULL;
243
244 switch (depth)
245 {
246 case 15:
247 redBits = 5;
248 greenBits = 5;
249 blueBits = 5;
250 break;
251
252 case 16:
253 redBits = 5;
254 greenBits = 6;
255 blueBits = 5;
256 break;
257
258 case 24: case 32:
259 redBits = 8;
260 greenBits = 8;
261 blueBits = 8;
262 break;
263
264 default:
265 free(visual);
266 return NULL;
267 }
268
269 visual->DBFlag = dbFlag;
270 visual->Depth = depth;
271 visual->GLVisual = _mesa_create_visual(GL_TRUE, /* rgb mode */
272 dbFlag, /* db_flag */
273 GL_FALSE, /* stereo */
274 redBits, greenBits, blueBits, 8,
275 0, /* index bits */
276 depthSize, /* depth bits */
277 stencilSize,/* stencil bits */
278 accumSize, /* accum bits */
279 accumSize, /* accum bits */
280 accumSize, /* accum bits */
281 accumSize, /* accum bits */
282 1 );
283 if (!visual->GLVisual)
284 {
285 free(visual);
286 return NULL;
287 }
288
289 return visual;
290 }
291
292
293 void AMesaDestroyVisual(AMesaVisual visual)
294 {
295 _mesa_destroy_visual(visual->GLVisual);
296 free(visual);
297 }
298
299
300 AMesaBuffer AMesaCreateBuffer(AMesaVisual visual,
301 GLint width, GLint height)
302 {
303 AMesaBuffer buffer;
304
305 buffer = (AMesaBuffer)calloc(1, sizeof(struct amesa_buffer));
306 if (!buffer)
307 return NULL;
308
309 buffer->Screen = NULL;
310 buffer->Background = NULL;
311 buffer->Active = NULL;
312 buffer->Width = width;
313 buffer->Height = height;
314
315 if (visual->DBFlag)
316 {
317 buffer->Background = create_bitmap_ex(visual->Depth, width, height);
318 if (!buffer->Background)
319 {
320 free(buffer);
321 return NULL;
322 }
323 }
324
325 buffer->GLBuffer = _mesa_create_framebuffer(visual->GLVisual);
326 if (!buffer->GLBuffer)
327 {
328 if (buffer->Background) destroy_bitmap(buffer->Background);
329 free(buffer);
330 return NULL;
331 }
332
333 return buffer;
334 }
335
336
337 void AMesaDestroyBuffer(AMesaBuffer buffer)
338 {
339 if (buffer->Screen) destroy_bitmap(buffer->Screen);
340 if (buffer->Background) destroy_bitmap(buffer->Background);
341 _mesa_unreference_framebuffer(&buffer->GLBuffer);
342 free(buffer);
343 }
344
345
346 AMesaContext AMesaCreateContext(AMesaVisual visual,
347 AMesaContext share)
348 {
349 AMesaContext context;
350 GLboolean direct = GL_FALSE;
351
352 context = (AMesaContext)calloc(1, sizeof(struct amesa_context));
353 if (!context)
354 return NULL;
355
356 context->Visual = visual;
357 context->Buffer = NULL;
358 context->ClearColor = 0;
359 context->CurrentColor = 0;
360 context->GLContext = _mesa_create_context(visual->GLVisual,
361 share ? share->GLContext : NULL,
362 (void *) context, GL_FALSE );
363 if (!context->GLContext)
364 {
365 free(context);
366 return NULL;
367 }
368
369 return context;
370 }
371
372
373 void AMesaDestroyContext(AMesaContext context)
374 {
375 _mesa_destroy_context(context->GLContext);
376 free(context);
377 }
378
379
380 GLboolean AMesaMakeCurrent(AMesaContext context, AMesaBuffer buffer)
381 {
382 if (context && buffer) {
383 set_color_depth(context->Visual->Depth);
384 if (set_gfx_mode(GFX_AUTODETECT, buffer->Width, buffer->Height, 0, 0) != 0)
385 return GL_FALSE;
386
387 context->Buffer = buffer;
388 buffer->Screen = screen;
389 buffer->Active = buffer->Background ? buffer->Background : screen;
390
391 setup_dd_pointers(context->GLContext);
392 _mesa_make_current(context->GLContext, buffer->GLBuffer);
393 }
394 else {
395 /* XXX I don't think you want to destroy anything here! */
396 destroy_bitmap(context->Buffer->Screen);
397 context->Buffer->Screen = NULL;
398 context->Buffer->Active = NULL;
399 context->Buffer = NULL;
400 _mesa_make_current(NULL, NULL);
401 }
402
403 return GL_TRUE;
404 }
405
406
407 void AMesaSwapBuffers(AMesaBuffer buffer)
408 {
409 if (buffer->Background) {
410 blit(buffer->Background, buffer->Screen,
411 0, 0, 0, 0,
412 buffer->Width, buffer->Height);
413 }
414 }