
Use _mesa_reference_framebuffer() and _mesa_unreference_framebuffer() functions to be sure reference counting is done correctly. Additional assertions are done too. Note _mesa_dereference_framebuffer() renamed to "unreference" as that's more accurate.
415 lines
13 KiB
C
415 lines
13 KiB
C
/*
|
|
* 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 "buffers.h"
|
|
#include "context.h"
|
|
#include "imports.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, GLframebuffer *buffer, GLuint bit)
|
|
{
|
|
AMesaContext context = (AMesaContext)(ctx->DriverCtx);
|
|
GLboolean ok = GL_TRUE;
|
|
|
|
if (bit == DD_FRONT_LEFT_BIT)
|
|
context->Buffer->Active = context->Buffer->Screen;
|
|
|
|
else if (bit == DD_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;
|
|
}
|
|
|
|
|
|
/**
|
|
* We only implement this function as a mechanism to check if the
|
|
* framebuffer size has changed (and update corresponding state).
|
|
*/
|
|
static void viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
|
|
{
|
|
/* poll for window size change and realloc software Z/stencil/etc if needed */
|
|
GLuint newWidth, newHeight;
|
|
GLframebuffer *buffer = ctx->WinSysDrawBuffer;
|
|
get_buffer_size( &newWidth, &newHeight );
|
|
if (buffer->Width != newWidth || buffer->Height != newHeight) {
|
|
_mesa_resize_framebuffer(ctx, buffer, newWidth, newHeight );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**********************************************************************/
|
|
/**********************************************************************/
|
|
|
|
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.Viewport = viewport;
|
|
|
|
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_unreference_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, GL_FALSE );
|
|
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);
|
|
}
|
|
else {
|
|
/* XXX I don't think you want to destroy anything here! */
|
|
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);
|
|
}
|
|
}
|