blob: 23ce8885096d6e6eefca3843a19737c6c25640c7 [file] [log] [blame]
/*
* Mesa 3-D graphics library
* Version: 3.0
* Copyright (C) 1995-1998 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <allegro.h>
#include "context.h"
#include "matrix.h"
#include "mtypes.h"
#include "GL/amesa.h"
struct amesa_visual
{
GLvisual *GLVisual; /* inherit from GLvisual */
GLboolean DBFlag; /* double buffered? */
GLuint Depth; /* bits per pixel ( >= 15 ) */
};
struct amesa_buffer
{
GLframebuffer *GLBuffer; /* inherit from GLframebuffer */
GLuint Width, Height;
BITMAP *Screen;
BITMAP *Background;
BITMAP *Active;
};
struct amesa_context
{
GLcontext *GLContext; /* inherit from GLcontext */
AMesaVisual Visual;
AMesaBuffer Buffer;
GLuint ClearColor;
GLuint CurrentColor;
};
static void setup_dd_pointers(GLcontext *ctx);
/**********************************************************************/
/***** drawing functions *****/
/**********************************************************************/
#define FLIP(context, y) (context->Buffer->Height - (y) - 1)
#include "allegro/generic.h"
#include "allegro/direct.h"
/**********************************************************************/
/***** 15-bit accelerated drawing funcs *****/
/**********************************************************************/
IMPLEMENT_WRITE_RGBA_SPAN(15, unsigned short)
IMPLEMENT_WRITE_RGB_SPAN(15, unsigned short)
IMPLEMENT_WRITE_MONO_RGBA_SPAN(15, unsigned short)
IMPLEMENT_READ_RGBA_SPAN(15, unsigned short)
IMPLEMENT_WRITE_RGBA_PIXELS(15, unsigned short)
IMPLEMENT_WRITE_MONO_RGBA_PIXELS(15, unsigned short)
IMPLEMENT_READ_RGBA_PIXELS(15, unsigned short)
/**********************************************************************/
/***** 16-bit accelerated drawing funcs *****/
/**********************************************************************/
IMPLEMENT_WRITE_RGBA_SPAN(16, unsigned short)
IMPLEMENT_WRITE_RGB_SPAN(16, unsigned short)
IMPLEMENT_WRITE_MONO_RGBA_SPAN(16, unsigned short)
IMPLEMENT_READ_RGBA_SPAN(16, unsigned short)
IMPLEMENT_WRITE_RGBA_PIXELS(16, unsigned short)
IMPLEMENT_WRITE_MONO_RGBA_PIXELS(16, unsigned short)
IMPLEMENT_READ_RGBA_PIXELS(16, unsigned short)
/**********************************************************************/
/***** 32-bit accelerated drawing funcs *****/
/**********************************************************************/
IMPLEMENT_WRITE_RGBA_SPAN(32, unsigned long)
IMPLEMENT_WRITE_RGB_SPAN(32, unsigned long)
IMPLEMENT_WRITE_MONO_RGBA_SPAN(32, unsigned long)
IMPLEMENT_READ_RGBA_SPAN(32, unsigned long)
IMPLEMENT_WRITE_RGBA_PIXELS(32, unsigned long)
IMPLEMENT_WRITE_MONO_RGBA_PIXELS(32, unsigned long)
IMPLEMENT_READ_RGBA_PIXELS(32, unsigned long)
/**********************************************************************/
/***** Miscellaneous device driver funcs *****/
/**********************************************************************/
static GLboolean set_buffer(GLcontext *ctx, GLenum mode)
{
AMesaContext context = (AMesaContext)(ctx->DriverCtx);
GLboolean ok = GL_TRUE;
if (mode == GL_FRONT_LEFT)
context->Buffer->Active = context->Buffer->Screen;
else if (mode == GL_BACK_LEFT)
{
if (context->Buffer->Background)
context->Buffer->Active = context->Buffer->Background;
else
ok = GL_FALSE;
}
else
ok = GL_FALSE;
return ok;
}
static void get_buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
{
AMesaContext context = (AMesaContext)(ctx->DriverCtx);
*width = context->Buffer->Width;
*height = context->Buffer->Height;
}
/**********************************************************************/
/**********************************************************************/
static void setup_dd_pointers(GLcontext *ctx)
{
AMesaContext context = (AMesaContext)(ctx->DriverCtx);
/* Initialize all the pointers in the driver struct. Do this whenever */
/* a new context is made current or we change buffers via set_buffer! */
ctx->Driver.UpdateState = setup_dd_pointers;
ctx->Driver.SetBuffer = set_buffer;
ctx->Driver.GetBufferSize = get_buffer_size;
ctx->Driver.Color = set_color_generic;
ctx->Driver.ClearColor = clear_color_generic;
ctx->Driver.Clear = clear_generic;
ctx->Driver.WriteRGBASpan = write_rgba_span_generic;
ctx->Driver.WriteRGBSpan = write_rgb_span_generic;
ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_generic;
ctx->Driver.WriteRGBAPixels = write_rgba_pixels_generic;
ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_generic;
ctx->Driver.ReadRGBASpan = read_rgba_span_generic;
ctx->Driver.ReadRGBAPixels = read_rgba_pixels_generic;
if (context->Buffer->Active != screen)
{
switch (context->Visual->Depth)
{
case 15:
ctx->Driver.WriteRGBASpan = write_rgba_span_15;
ctx->Driver.WriteRGBSpan = write_rgb_span_15;
ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_15;
ctx->Driver.WriteRGBAPixels = write_rgba_pixels_15;
ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_15;
ctx->Driver.ReadRGBASpan = read_rgba_span_15;
ctx->Driver.ReadRGBAPixels = read_rgba_pixels_15;
break;
case 16:
ctx->Driver.WriteRGBASpan = write_rgba_span_16;
ctx->Driver.WriteRGBSpan = write_rgb_span_16;
ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_16;
ctx->Driver.WriteRGBAPixels = write_rgba_pixels_16;
ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_16;
ctx->Driver.ReadRGBASpan = read_rgba_span_16;
ctx->Driver.ReadRGBAPixels = read_rgba_pixels_16;
break;
case 32:
ctx->Driver.WriteRGBASpan = write_rgba_span_32;
ctx->Driver.WriteRGBSpan = write_rgb_span_32;
ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_32;
ctx->Driver.WriteRGBAPixels = write_rgba_pixels_32;
ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_32;
ctx->Driver.ReadRGBASpan = read_rgba_span_32;
ctx->Driver.ReadRGBAPixels = read_rgba_pixels_32;
break;
}
}
}
/**********************************************************************/
/***** AMesa Public API Functions *****/
/**********************************************************************/
AMesaVisual AMesaCreateVisual(GLboolean dbFlag, GLint depth,
GLint depthSize, GLint stencilSize, GLint accumSize)
{
AMesaVisual visual;
GLbyte redBits, greenBits, blueBits;
visual = (AMesaVisual)calloc(1, sizeof(struct amesa_visual));
if (!visual)
return NULL;
switch (depth)
{
case 15:
redBits = 5;
greenBits = 5;
blueBits = 5;
break;
case 16:
redBits = 5;
greenBits = 6;
blueBits = 5;
break;
case 24: case 32:
redBits = 8;
greenBits = 8;
blueBits = 8;
break;
default:
free(visual);
return NULL;
}
visual->DBFlag = dbFlag;
visual->Depth = depth;
visual->GLVisual = _mesa_create_visual(GL_TRUE, /* rgb mode */
dbFlag, /* db_flag */
GL_FALSE, /* stereo */
redBits, greenBits, blueBits, 8,
0, /* index bits */
depthSize, /* depth bits */
stencilSize,/* stencil bits */
accumSize, /* accum bits */
accumSize, /* accum bits */
accumSize, /* accum bits */
accumSize, /* accum bits */
1 );
if (!visual->GLVisual)
{
free(visual);
return NULL;
}
return visual;
}
void AMesaDestroyVisual(AMesaVisual visual)
{
_mesa_destroy_visual(visual->GLVisual);
free(visual);
}
AMesaBuffer AMesaCreateBuffer(AMesaVisual visual,
GLint width, GLint height)
{
AMesaBuffer buffer;
buffer = (AMesaBuffer)calloc(1, sizeof(struct amesa_buffer));
if (!buffer)
return NULL;
buffer->Screen = NULL;
buffer->Background = NULL;
buffer->Active = NULL;
buffer->Width = width;
buffer->Height = height;
if (visual->DBFlag)
{
buffer->Background = create_bitmap_ex(visual->Depth, width, height);
if (!buffer->Background)
{
free(buffer);
return NULL;
}
}
buffer->GLBuffer = _mesa_create_framebuffer(visual->GLVisual);
if (!buffer->GLBuffer)
{
if (buffer->Background) destroy_bitmap(buffer->Background);
free(buffer);
return NULL;
}
return buffer;
}
void AMesaDestroyBuffer(AMesaBuffer buffer)
{
if (buffer->Screen) destroy_bitmap(buffer->Screen);
if (buffer->Background) destroy_bitmap(buffer->Background);
_mesa_destroy_framebuffer(buffer->GLBuffer);
free(buffer);
}
AMesaContext AMesaCreateContext(AMesaVisual visual,
AMesaContext share)
{
AMesaContext context;
GLboolean direct = GL_FALSE;
context = (AMesaContext)calloc(1, sizeof(struct amesa_context));
if (!context)
return NULL;
context->Visual = visual;
context->Buffer = NULL;
context->ClearColor = 0;
context->CurrentColor = 0;
context->GLContext = _mesa_create_context(visual->GLVisual,
share ? share->GLContext : NULL,
(void*)context,
direct);
if (!context->GLContext)
{
free(context);
return NULL;
}
return context;
}
void AMesaDestroyContext(AMesaContext context)
{
_mesa_destroy_context(context->GLContext);
free(context);
}
GLboolean AMesaMakeCurrent(AMesaContext context, AMesaBuffer buffer)
{
if (context && buffer) {
set_color_depth(context->Visual->Depth);
if (set_gfx_mode(GFX_AUTODETECT, buffer->Width, buffer->Height, 0, 0) != 0)
return GL_FALSE;
context->Buffer = buffer;
buffer->Screen = screen;
buffer->Active = buffer->Background ? buffer->Background : screen;
setup_dd_pointers(context->GLContext);
_mesa_make_current(context->GLContext, buffer->GLBuffer);
gl_Viewport(context->GLContext, 0, 0, buffer->Width, buffer->Height);
}
else {
destroy_bitmap(context->Buffer->Screen);
context->Buffer->Screen = NULL;
context->Buffer->Active = NULL;
context->Buffer = NULL;
_mesa_make_current(NULL, NULL);
}
return GL_TRUE;
}
void AMesaSwapBuffers(AMesaBuffer buffer)
{
if (buffer->Background) {
blit(buffer->Background, buffer->Screen,
0, 0, 0, 0,
buffer->Width, buffer->Height);
}
}