This is ddsample.c in view mode; [Download] [Up]
/* $Id: ddsample.c,v 1.5 1997/06/04 00:30:40 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 2.3 * Copyright (C) 1995-1997 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. */ /* * $Log: ddsample.c,v $ * Revision 1.5 1997/06/04 00:30:40 brianp * replaced VB->Unclipped with VB->ClipMask * * Revision 1.4 1997/05/26 21:15:37 brianp * now pass red/green/blue/alpha bits to gl_create_visual() * * Revision 1.3 1996/11/13 03:52:12 brianp * updated comments * * Revision 1.2 1996/09/15 14:30:27 brianp * updated for new GLframebuffer and GLvisual datatypes and functions * * Revision 1.1 1996/09/13 01:38:16 brianp * Initial revision * */ /* * This is a sample template for writing new Mesa device drivers. * You'll have to rewrite all the pseudo code below. * * Let's say you're interfacing Mesa to a window/operating system * called FOO. Replace all occurances of FOOMesa with the real name * you select for your interface (i.e. XMesa, WMesa, AmigaMesa). * * You'll have to design an API for clients to use, defined in a * header called Mesa/include/GL/FooMesa.h Use the sample as an * example. The API should at least have functions for creating * rendering contexts, binding rendering contexts to windows/frame * buffers, etc. * * Next, you'll have to write implementations for the device driver * functions described in dd.h * * Note that you'll usually have to flip Y coordinates since Mesa's * window coordinates start at the bottom and increase upward. Most * window system's Y-axis increases downward * * Functions marked OPTIONAL may be completely omitted by your driver. * * Your Makefile should compile this module along with the rest of * the core Mesa library. */ #include <stdlib.h> #include "GL/FooMesa.h" #include "context.h" #include "types.h" #include "vb.h" /* * This struct describes the attributes (number of channels, video mode, * bits per pixel, etc) for a drawable (window, screen, or frame buffer). */ struct foo_mesa_visual { GLvisual *gl_visual; GLboolean db_flag; /* double buffered? */ GLboolean rgb_flag; /* RGB mode? */ GLuint depth; /* bits per pixel (1, 8, 24, etc) */ }; /* * This struct is a wrapper for your system's notion of a window or * frame buffer. It's needed because most window systems don't have * any notion of the Z buffers, stencil buffers, etc needed by Mesa. */ struct foo_mesa_buffer { GLframebuffer *gl_buffer; /* The depth, stencil, accum, etc buffers */ WindowType *the_window; /* your window handle, etc */ }; /* * This struct contains all device-driver state information. Think of it * as an extension of the core GLcontext from types.h. */ struct foo_mesa_context { GLcontext *gl_ctx; /* the core library context */ FooMesaVisual visual; FooMesaBuffer buffer; unsigned long pixel; /* current color index or RGBA pixel value */ unsigned long clearpixel; /* pixel for clearing the color buffers */ /* etc... */ }; /**********************************************************************/ /***** Miscellaneous device driver funcs *****/ /**********************************************************************/ static void finish( GLcontext *ctx ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* OPTIONAL FUNCTION: implements glFinish if possible */ } static void flush( GLcontext *ctx ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* OPTIONAL FUNCTION: implements glFlush if possible */ } static void clear_index( GLcontext *ctx, GLuint index ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* implement glClearIndex */ /* usually just save the color index value in the foo struct */ } static void clear_color( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* implement glClearColor */ /* color components are floats in [0,1] */ /* usually just save the value in the foo struct */ } static void clear( GLcontext *ctx, GLboolean all, GLint x, GLint y, GLint width, GLint height ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* * Clear the specified region of the current color buffer using the clear * color or index as specified by one of the two functions above. * If all==GL_TRUE, clear whole buffer, else just clear region defined * by x,y,width,height */ } static void set_index( GLcontext *ctx, GLuint index ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* Set the current color index. */ } static void set_color( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* Set the current RGBA color. */ /* r is in [0,ctx->Visual->RedScale] */ /* g is in [0,ctx->Visual->GreenScale] */ /* b is in [0,ctx->Visual->BlueScale] */ /* a is in [0,ctx->Visual->AlphaScale] */ } static GLboolean index_mask( GLcontext *ctx, GLuint mask ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* OPTIONAL FUNCTION: implement glIndexMask if possible, else * return GL_FALSE */ } static GLboolean color_mask( GLcontext *ctx, GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* OPTIONAL FUNCTION: implement glColorMask if possible, else * return GL_FALSE */ } static GLboolean logicop( GLcontext *ctx, GLenum op ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* * OPTIONAL FUNCTION: * Implements glLogicOp if possible. Return GL_TRUE if the device driver * can perform the operation, otherwise return GL_FALSE. If GL_FALSE * is returned, the logic op will be done in software by Mesa. */ } static void dither( GLcontext *ctx, GLboolean enable ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* OPTIONAL FUNCTION: enable/disable dithering if applicable */ } static GLboolean set_buffer( GLcontext *ctx, GLenum mode ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* set the current drawing/reading buffer, return GL_TRUE or GL_FALSE */ /* for success/failure */ setup_DD_pointers( ctx ); } static void get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height ) { struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx; /* return the width and height of the current buffer */ /* if anything special has to been done when the buffer/window is */ /* resized, do it now */ } /**********************************************************************/ /***** Accelerated point, line, triangle rendering *****/ /**********************************************************************/ /* There may several functions like this, for different screen modes, etc */ static void fast_points_function( GLcontext *ctx, GLuint first, GLuint last ) { struct vertex_buffer *VB = ctx->VB; /* Render a number of points by some hardware/OS accerated method */ if (VB->MonoColor) { /* draw all points using the current color (set_color) */ for (i=first;i<=last;i++) { if (VB->ClipMask[i]==0) { /* compute window coordinate */ int x, y; x = (GLint) VB->Win[i][0]; y = FLIP( (GLint) VB->Win[i][1] ); PLOT_PIXEL( x, y, currentcolor ); } } } else { /* each point is a different color */ for (i=first;i<=last;i++) { if (VB->ClipMask[i]==0) { int x, y; x = (GLint) VB->Win[i][0]; y = FLIP( (GLint) VB->Win[i][1] ); PLOT_PIXEL( x, y, VB->Color[i] ); } } } } /* There may several functions like this, for different screen modes, etc */ static void fast_line_function( GLcontext *ctx, GLuint v0, GLuint v1, GLuint pv ) { /* Render a line by some hardware/OS accerated method */ struct vertex_buffer *VB = ctx->VB; int x0, y0, x1, y1; unsigned long pixel; if (VB->MonoColor) { pixel = current color; } else { pixel = VB->Color[pv]; } x0 = (int) VB->Win[v0][0]; y0 = FLIP( (int) VB->Win[v0][1] ); x1 = (int) VB->Win[v1][0]; y1 = FLIP( (int) VB->Win[v1][1] ); DRAW_LINE( x0,y0, x1,y1, pixel ); } /* There may several functions like this, for different screen modes, etc */ static void fast_triangle_function( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv ) { /* Render a triangle by some hardware/OS accerated method */ struct vertex_buffer *VB = ctx->VB; int i; if (VB->MonoColor) { pixel = current color or index; } else { pixel = VB->Color[pv] or VB->Index[pv]; } DRAW_TRIANGLE( v0, v1, v2 ); } /**********************************************************************/ /***** Write spans of pixels *****/ /**********************************************************************/ static void write_index_span( GLcontext *ctx, GLuint n, GLint x, GLint y, const GLuint index[], const GLubyte mask[] ) { int i; for (i=0;i<n;i++) { if (mask[i]) { /* draw pixel (x[i],y[i]) using index[i] */ } } } static void write_monoindex_span( GLcontext *ctx, GLuint n,GLint x,GLint y,const GLubyte mask[] ) { int i; for (i=0;i<n;i++) { if (mask[i]) { /* draw pixel (x[i],y[i]) using current color index */ } } } static void write_color_span( GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte red[], const GLubyte green[], const GLubyte blue[], const GLubyte alpha[], const GLubyte mask[] ) { int i; y=FLIP(y); if (mask) { /* draw some pixels */ for (i=0; i<n; i++, x++) { if (mask[i]) { /* draw pixel x,y using color red[i]/green[i]/blue[i]/alpha[i] */ } } } else { /* draw all pixels */ for (i=0; i<n; i++, x++) { /* draw pixel x,y using color red[i]/green[i]/blue[i]/alpha[i] */ } } } static void write_monocolor_span( GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte mask[]) { int i; y=FLIP(y); for (i=0; i<n; i++, x++) { if (mask[i]) { plot pixel (x,y) using current color } } } /**********************************************************************/ /***** Read spans of pixels *****/ /**********************************************************************/ static void read_index_span( GLcontext *ctx, GLuint n, GLint x, GLint y, GLuint index[]) { int i; for (i=0; i<n; i++) { index[i] = read_pixel(x[i],y[i]); } } static void read_color_span( GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte red[], GLubyte green[], GLubyte blue[], GLubyte alpha[] ) { int i; for (i=0; i<n; i++, x++) { red[i] = read_red( x, y ); green[i] = read_green( x, y ); /* etc */ } } /**********************************************************************/ /***** Write arrays of pixels *****/ /**********************************************************************/ static void write_index_pixels( GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLuint index[], const GLubyte mask[] ) { int i; for (i=0; i<n; i++) { if (mask[i]) { plot pixel x[i], y[i] using index[i] } } } static void write_monoindex_pixels( GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte mask[] ) { int i; for (i=0; i<n; i++) { if (mask[i]) { write pixel x[i], y[i] using current index } } } static void write_color_pixels( GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte r[], const GLubyte g[], const GLubyte b[], const GLubyte a[], const GLubyte mask[] ) { int i; for (i=0; i<n; i++) { if (mask[i]) { write pixel x[i], y[i] using red[i],green[i],blue[i],alpha[i] } } } static void write_monocolor_pixels( GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte mask[] ) { int i; for (i=0; i<n; i++) { if (mask[i]) { write pixel x[i], y[i] using current color } } } /**********************************************************************/ /***** Read arrays of pixels *****/ /**********************************************************************/ /* Read an array of color index pixels. */ static void read_index_pixels( GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLuint indx[], const GLubyte mask[] ) { int i; for (i=0; i<n; i++) { if (mask[i]) { index[i] = read_pixel( x[i], y[i] ); } } } static void read_color_pixels( GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte red[], GLubyte green[], GLubyte blue[], GLubyte alpha[], const GLubyte mask[] ) { int i; for (i=0; i<n; i++) { if (mask[i]) { red[i] = read_red( x[i], y[i] ); green[i] = read_green( x[i], y[i] ); /* etc */ } } } /**********************************************************************/ /**********************************************************************/ static void setup_DD_pointers( GLcontext *ctx ) { /* Initialize all the pointers in the DD 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.ClearIndex = clear_index; ctx->Driver.ClearColor = clear_color; ctx->Driver.Clear = clear; ctx->Driver.Index = set_index; ctx->Driver.Color = set_color; ctx->Driver.SetBuffer = set_buffer; ctx->Driver.GetBufferSize = get_buffer_size; ctx->Driver.PointsFunc = fast_points_function; ctx->Driver.LineFunc = fast_line_function; ctx->Driver.TriangleFunc = fast_triangle_function; /* Pixel/span writing functions: */ ctx->Driver.WriteColorSpan = write_color_span; ctx->Driver.WriteMonocolorSpan = write_monocolor_span; ctx->Driver.WriteColorPixels = write_color_pixels; ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels; ctx->Driver.WriteIndexSpan = write_index_span; ctx->Driver.WriteMonoindexSpan = write_monoindex_span; ctx->Driver.WriteIndexPixels = write_index_pixels; ctx->Driver.WriteMonoindexPixels = write_monoindex_pixels; /* Pixel/span reading functions: */ ctx->Driver.ReadIndexSpan = read_index_span; ctx->Driver.ReadColorSpan = read_color_span; ctx->Driver.ReadIndexPixels = read_index_pixels; ctx->Driver.ReadColorPixels = read_color_pixels; /* * OPTIONAL FUNCTIONS: these may be left uninitialized if the device * driver can't/needn't implement them. */ #if 0 ctx->Driver.Finish = finish; ctx->Driver.Flush = flush; ctx->Driver.IndexMask = index_mask; ctx->Driver.ColorMask = color_mask; ctx->Driver.LogicOp = logicop; ctx->Driver.Dither = dither; #endif } /**********************************************************************/ /***** FOO/Mesa API Functions *****/ /**********************************************************************/ /* * The exact arguments to this function will depend on your window system */ FooMesaVisual FooMesaCreateVisual( GLboolean rgb_mode, GLboolean db_flag, /* etc... */ ) { FooMesaVisual v; GLfloat redscale, greenscale, bluescale, alphascale; v = (FooMesaVisual) calloc( 1, sizeof(struct foo_mesa_visual) ); if (!v) { return NULL; } if (rgb_mode) { /* RGB(A) mode */ redscale = ??; greedscale = ??; bluescale = ??; alphascale = ??; redbits = ??; greenbits = ??; bluebits = ??; alphabits = ??; index_bits = 0; } else { /* color index mode */ redscale = 0.0; greedscale = 0.0; bluescale = 0.0; alphascale = 0.0; redbits = 0; greenbits = 0; bluebits = 0; alphabits = 0; index_bits = ??; } /* Create core visual */ v->gl_visual = gl_create_visual( rgb_mode, alpha_flag, db_flag, depth_size, stencil_size, accum_size, index_bits, redscale, greenscale, bluescale, alphascale, redbits, greenbits, bluebits, alphabits; return v; } void FooMesaDestroyVisual( FooMesaVisual v ) { gl_destroy_visual( v->gl_visual ); free( v ); } FooMesaBuffer FooMesaCreateBuffer( FooMesaVisual visual, int /* your window id */ ) { FooMesaBuffer b; b = (FooMesaBuffer) calloc( 1, sizeof(struct foo_mesa_buffer) ); if (!b) { return NULL; } b->gl_buffer = gl_create_buffer( visual->gl_visual, windowid, 0, 0 ); /* other stuff */ return b; } void FooMesaDestroyBuffer( FooMesaBuffer b ) { gl_destroy_buffer( b->gl_buffer ); free( b ); } FooMesaContext FooMesaCreateContext( FooMesaVisual visual, FooMesaContext share ) { FooMesaContext c; c = (FooMesaContext) calloc( 1, sizeof(struct foo_mesa_context) ); if (!c) { return NULL; } c->gl_ctx = gl_create_context( visual->gl_visual, share ? share->gl_ctx : NULL, (void *) c ); /* you probably have to do a bunch of other initializations here. */ return c; } void FooMesaDestroyContext( FooMesaContext c ) { gl_destroy_context( c->gl_ctx ); free( c ); } /* * Make the specified context the current one */ * Might also want to specify the window/drawable here, like for GLX. */ void FooMesaMakeCurrent( FooMesaContext c, FooMesaBuffer b ) { if (c && b) { gl_make_current( c->gl_ctx, b->gl_buffer ); Current_context = c; if (c->gl_ctx->Viewport.Width==0) { /* initialize viewport to window size */ gl_Viewport( c->gl_ctx, 0, 0, c->width, c->height ); } } else { /* Detach */ gl_make_current( NULL, NULL ); Current = NULL; } } void FooMesaSwapBuffers( FooMesaBuffer b ) { /* copy/swap back buffer to front if applicable */ } /* you may need to add other FOO/Mesa functions too... */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.