Use the faster span read/write template for 16bpp
[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 static void viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
149 {
150 /* poll for window size change and realloc software Z/stencil/etc if needed */
151 _mesa_ResizeBuffersMESA();
152 }
153
154
155 /**********************************************************************/
156 /**********************************************************************/
157
158 static void setup_dd_pointers(GLcontext *ctx)
159 {
160 AMesaContext context = (AMesaContext)(ctx->DriverCtx);
161
162 /* Initialize all the pointers in the driver struct. Do this whenever */
163 /* a new context is made current or we change buffers via set_buffer! */
164
165 ctx->Driver.UpdateState = setup_dd_pointers;
166 ctx->Driver.SetBuffer = set_buffer;
167 ctx->Driver.GetBufferSize = get_buffer_size;
168 ctx->Driver.Viewport = viewport;
169
170 ctx->Driver.Color = set_color_generic;
171 ctx->Driver.ClearColor = clear_color_generic;
172 ctx->Driver.Clear = clear_generic;
173 ctx->Driver.WriteRGBASpan = write_rgba_span_generic;
174 ctx->Driver.WriteRGBSpan = write_rgb_span_generic;
175 ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_generic;
176 ctx->Driver.WriteRGBAPixels = write_rgba_pixels_generic;
177 ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_generic;
178 ctx->Driver.ReadRGBASpan = read_rgba_span_generic;
179 ctx->Driver.ReadRGBAPixels = read_rgba_pixels_generic;
180
181 if (context->Buffer->Active != screen)
182 {
183 switch (context->Visual->Depth)
184 {
185 case 15:
186 ctx->Driver.WriteRGBASpan = write_rgba_span_15;
187 ctx->Driver.WriteRGBSpan = write_rgb_span_15;
188 ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_15;
189 ctx->Driver.WriteRGBAPixels = write_rgba_pixels_15;
190 ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_15;
191 ctx->Driver.ReadRGBASpan = read_rgba_span_15;
192 ctx->Driver.ReadRGBAPixels = read_rgba_pixels_15;
193 break;
194
195 case 16:
196 ctx->Driver.WriteRGBASpan = write_rgba_span_16;
197 ctx->Driver.WriteRGBSpan = write_rgb_span_16;
198 ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_16;
199 ctx->Driver.WriteRGBAPixels = write_rgba_pixels_16;
200 ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_16;
201 ctx->Driver.ReadRGBASpan = read_rgba_span_16;
202 ctx->Driver.ReadRGBAPixels = read_rgba_pixels_16;
203 break;
204
205 case 32:
206 ctx->Driver.WriteRGBASpan = write_rgba_span_32;
207 ctx->Driver.WriteRGBSpan = write_rgb_span_32;
208 ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_32;
209 ctx->Driver.WriteRGBAPixels = write_rgba_pixels_32;
210 ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_32;
211 ctx->Driver.ReadRGBASpan = read_rgba_span_32;
212 ctx->Driver.ReadRGBAPixels = read_rgba_pixels_32;
213 break;
214 }
215 }
216 }
217
218
219 /**********************************************************************/
220 /***** AMesa Public API Functions *****/
221 /**********************************************************************/
222
223
224 AMesaVisual AMesaCreateVisual(GLboolean dbFlag, GLint depth,
225 GLint depthSize, GLint stencilSize, GLint accumSize)
226 {
227 AMesaVisual visual;
228 GLbyte redBits, greenBits, blueBits;
229
230 visual = (AMesaVisual)calloc(1, sizeof(struct amesa_visual));
231 if (!visual)
232 return NULL;
233
234 switch (depth)
235 {
236 case 15:
237 redBits = 5;
238 greenBits = 5;
239 blueBits = 5;
240 break;
241
242 case 16:
243 redBits = 5;
244 greenBits = 6;
245 blueBits = 5;
246 break;
247
248 case 24: case 32:
249 redBits = 8;
250 greenBits = 8;
251 blueBits = 8;
252 break;
253
254 default:
255 free(visual);
256 return NULL;
257 }
258
259 visual->DBFlag = dbFlag;
260 visual->Depth = depth;
261 visual->GLVisual = _mesa_create_visual(GL_TRUE, /* rgb mode */
262 dbFlag, /* db_flag */
263 GL_FALSE, /* stereo */
264 redBits, greenBits, blueBits, 8,
265 0, /* index bits */
266 depthSize, /* depth bits */
267 stencilSize,/* stencil bits */
268 accumSize, /* accum bits */
269 accumSize, /* accum bits */
270 accumSize, /* accum bits */
271 accumSize, /* accum bits */
272 1 );
273 if (!visual->GLVisual)
274 {
275 free(visual);
276 return NULL;
277 }
278
279 return visual;
280 }
281
282
283 void AMesaDestroyVisual(AMesaVisual visual)
284 {
285 _mesa_destroy_visual(visual->GLVisual);
286 free(visual);
287 }
288
289
290 AMesaBuffer AMesaCreateBuffer(AMesaVisual visual,
291 GLint width, GLint height)
292 {
293 AMesaBuffer buffer;
294
295 buffer = (AMesaBuffer)calloc(1, sizeof(struct amesa_buffer));
296 if (!buffer)
297 return NULL;
298
299 buffer->Screen = NULL;
300 buffer->Background = NULL;
301 buffer->Active = NULL;
302 buffer->Width = width;
303 buffer->Height = height;
304
305 if (visual->DBFlag)
306 {
307 buffer->Background = create_bitmap_ex(visual->Depth, width, height);
308 if (!buffer->Background)
309 {
310 free(buffer);
311 return NULL;
312 }
313 }
314
315 buffer->GLBuffer = _mesa_create_framebuffer(visual->GLVisual);
316 if (!buffer->GLBuffer)
317 {
318 if (buffer->Background) destroy_bitmap(buffer->Background);
319 free(buffer);
320 return NULL;
321 }
322
323 return buffer;
324 }
325
326
327 void AMesaDestroyBuffer(AMesaBuffer buffer)
328 {
329 if (buffer->Screen) destroy_bitmap(buffer->Screen);
330 if (buffer->Background) destroy_bitmap(buffer->Background);
331 _mesa_destroy_framebuffer(buffer->GLBuffer);
332 free(buffer);
333 }
334
335
336 AMesaContext AMesaCreateContext(AMesaVisual visual,
337 AMesaContext share)
338 {
339 AMesaContext context;
340 GLboolean direct = GL_FALSE;
341
342 context = (AMesaContext)calloc(1, sizeof(struct amesa_context));
343 if (!context)
344 return NULL;
345
346 context->Visual = visual;
347 context->Buffer = NULL;
348 context->ClearColor = 0;
349 context->CurrentColor = 0;
350 context->GLContext = _mesa_create_context(visual->GLVisual,
351 share ? share->GLContext : NULL,
352 (void *) context, GL_FALSE );
353 if (!context->GLContext)
354 {
355 free(context);
356 return NULL;
357 }
358
359 return context;
360 }
361
362
363 void AMesaDestroyContext(AMesaContext context)
364 {
365 _mesa_destroy_context(context->GLContext);
366 free(context);
367 }
368
369
370 GLboolean AMesaMakeCurrent(AMesaContext context, AMesaBuffer buffer)
371 {
372 if (context && buffer) {
373 set_color_depth(context->Visual->Depth);
374 if (set_gfx_mode(GFX_AUTODETECT, buffer->Width, buffer->Height, 0, 0) != 0)
375 return GL_FALSE;
376
377 context->Buffer = buffer;
378 buffer->Screen = screen;
379 buffer->Active = buffer->Background ? buffer->Background : screen;
380
381 setup_dd_pointers(context->GLContext);
382 _mesa_make_current(context->GLContext, buffer->GLBuffer);
383 }
384 else {
385 /* XXX I don't think you want to destroy anything here! */
386 destroy_bitmap(context->Buffer->Screen);
387 context->Buffer->Screen = NULL;
388 context->Buffer->Active = NULL;
389 context->Buffer = NULL;
390 _mesa_make_current(NULL, NULL);
391 }
392
393 return GL_TRUE;
394 }
395
396
397 void AMesaSwapBuffers(AMesaBuffer buffer)
398 {
399 if (buffer->Background) {
400 blit(buffer->Background, buffer->Screen,
401 0, 0, 0, 0,
402 buffer->Width, buffer->Height);
403 }
404 }