-/* $Id: drawpix.c,v 1.6 1999/11/11 01:22:26 brianp Exp $ */
+/* $Id: drawpix.c,v 1.22 2000/05/04 13:48:49 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
*
- * Copyright (C) 1999 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
#include "feedback.h"
#include "image.h"
#include "macros.h"
+#include "mem.h"
#include "mmath.h"
#include "pixel.h"
+#include "pixeltex.h"
#include "span.h"
+#include "state.h"
#include "stencil.h"
+#include "texture.h"
#include "types.h"
#include "zoom.h"
#endif
+/*
+ * Given the dest position, size and skipPixels and skipRows values
+ * for a glDrawPixels command, perform clipping of the image bounds
+ * so the result lies withing the context's buffer bounds.
+ * Return: GL_TRUE if image is ready for drawing
+ * GL_FALSE if image was completely clipped away (draw nothing)
+ */
+GLboolean
+_mesa_clip_pixelrect(const GLcontext *ctx,
+ GLint *destX, GLint *destY,
+ GLsizei *width, GLsizei *height,
+ GLint *skipPixels, GLint *skipRows)
+{
+ const GLframebuffer *buffer = ctx->DrawBuffer;
+
+ /* left clipping */
+ if (*destX < buffer->Xmin) {
+ *skipPixels += (buffer->Xmin - *destX);
+ *width -= (buffer->Xmin - *destX);
+ *destX = buffer->Xmin;
+ }
+ /* right clipping */
+ if (*destX + *width > buffer->Xmax)
+ *width -= (*destX + *width - buffer->Xmax - 1);
+
+ if (*width <= 0)
+ return GL_FALSE;
+
+ /* bottom clipping */
+ if (*destY < buffer->Ymin) {
+ *skipRows += (buffer->Ymin - *destY);
+ *height -= (buffer->Ymin - *destY);
+ *destY = buffer->Ymin;
+ }
+ /* top clipping */
+ if (*destY + *height > buffer->Ymax)
+ *height -= (*destY + *height - buffer->Ymax - 1);
+
+ if (*height <= 0)
+ return GL_TRUE;
+
+ return GL_TRUE;
+}
+
+
+
/*
* Try to do a fast and simple RGB(a) glDrawPixels.
* Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
return GL_TRUE;
}
- if (ctx->NewState) {
- gl_update_state(ctx);
- }
-
- /* see if device driver can do the drawpix */
- if (ctx->Driver.DrawPixels
- && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
- unpack, pixels)) {
- return GL_TRUE;
- }
-
if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0
- && ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0
- && ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0
- && ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0
- && ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0
+ && !ctx->Pixel.ScaleOrBiasRGBA
+ && !ctx->Pixel.ScaleOrBiasRGBApcm
+ && ctx->ColorMatrix.type == MATRIX_IDENTITY
+ && !ctx->Pixel.ColorTableEnabled
+ && !ctx->Pixel.PostColorMatrixColorTableEnabled
+ && !ctx->Pixel.MinMaxEnabled
+ && !ctx->Pixel.HistogramEnabled
&& ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0
&& ctx->Pixel.MapColorFlag==0
+ && ctx->Texture.ReallyEnabled == 0
&& unpack->Alignment==1
&& !unpack->SwapBytes
&& !unpack->LsbFirst) {
*/
if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
/* horizontal clipping */
- if (destX < ctx->Buffer->Xmin) {
- skipPixels += (ctx->Buffer->Xmin - destX);
- drawWidth -= (ctx->Buffer->Xmin - destX);
- destX = ctx->Buffer->Xmin;
+ if (destX < ctx->DrawBuffer->Xmin) {
+ skipPixels += (ctx->DrawBuffer->Xmin - destX);
+ drawWidth -= (ctx->DrawBuffer->Xmin - destX);
+ destX = ctx->DrawBuffer->Xmin;
}
- if (destX + drawWidth > ctx->Buffer->Xmax)
- drawWidth -= (destX + drawWidth - ctx->Buffer->Xmax - 1);
+ if (destX + drawWidth > ctx->DrawBuffer->Xmax)
+ drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax - 1);
if (drawWidth <= 0)
return GL_TRUE;
/* vertical clipping */
- if (destY < ctx->Buffer->Ymin) {
- skipRows += (ctx->Buffer->Ymin - destY);
- drawHeight -= (ctx->Buffer->Ymin - destY);
- destY = ctx->Buffer->Ymin;
+ if (destY < ctx->DrawBuffer->Ymin) {
+ skipRows += (ctx->DrawBuffer->Ymin - destY);
+ drawHeight -= (ctx->DrawBuffer->Ymin - destY);
+ destY = ctx->DrawBuffer->Ymin;
}
- if (destY + drawHeight > ctx->Buffer->Ymax)
- drawHeight -= (destY + drawHeight - ctx->Buffer->Ymax - 1);
+ if (destY + drawHeight > ctx->DrawBuffer->Ymax)
+ drawHeight -= (destY + drawHeight - ctx->DrawBuffer->Ymax - 1);
if (drawHeight <= 0)
return GL_TRUE;
+
+ zoomY0 = 0; /* not used - silence compiler warning */
}
else {
/* setup array of fragment Z value to pass to zoom function */
- GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
+ GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
GLint i;
assert(drawWidth < MAX_WIDTH);
for (i=0; i<drawWidth; i++)
GLint row;
for (row=0; row<drawHeight; row++) {
assert(drawWidth < MAX_WIDTH);
- gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
+ _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
(*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
(const GLubyte (*)[4])rgba,
NULL);
GLint row;
for (row=0; row<drawHeight; row++) {
assert(drawWidth < MAX_WIDTH);
- gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
+ _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
zSpan, (void *) rgba, zoomY0);
src += rowLength;
drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
/* Fragment depth values */
- if (ctx->Depth.Test) {
- GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
+ if (ctx->Depth.Test || ctx->Fog.Enabled) {
+ GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
GLint i;
for (i = 0; i < drawWidth; i++) {
zspan[i] = zval;
*/
for (row = 0; row < height; row++, y++) {
GLuint indexes[MAX_WIDTH];
- const GLvoid *source = gl_pixel_addr_in_image(&ctx->Unpack,
+ const GLvoid *source = _mesa_image_address(&ctx->Unpack,
pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
_mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, indexes,
type, source, &ctx->Unpack, GL_TRUE);
GLenum type, const GLvoid *pixels )
{
const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
+ const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
const GLint desty = y;
GLint row, drawWidth;
GLstencil values[MAX_WIDTH];
GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
- const GLvoid *source = gl_pixel_addr_in_image(&ctx->Unpack,
+ const GLvoid *source = _mesa_image_address(&ctx->Unpack,
pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
_mesa_unpack_index_span(ctx, drawWidth, destType, values,
- type, source, &ctx->Unpack, GL_TRUE);
+ type, source, &ctx->Unpack, GL_FALSE);
+ if (shift_or_offset) {
+ _mesa_shift_and_offset_stencil( ctx, drawWidth, values );
+ }
+ if (ctx->Pixel.MapStencilFlag) {
+ _mesa_map_stencil( ctx, drawWidth, values );
+ }
if (zoom) {
gl_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y,
values, desty );
}
else {
- gl_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values );
+ _mesa_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values );
}
}
}
/* Special case: directly write 16-bit depth values */
GLint row;
for (row = 0; row < height; row++, y++) {
- const GLdepth *zptr = gl_pixel_addr_in_image(&ctx->Unpack,
+ GLdepth zspan[MAX_WIDTH];
+ const GLushort *zptr = _mesa_image_address(&ctx->Unpack,
pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
- gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
+ GLint i;
+ for (i = 0; i < width; i++)
+ zspan[i] = zptr[i];
+ gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
}
}
- else if (type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint)
+ else if (type==GL_UNSIGNED_INT && ctx->Visual->DepthBits == 32
&& !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
/* Special case: directly write 32-bit depth values */
- GLint i, row;
- /* Compute shift value to scale 32-bit uints down to depth values. */
- GLuint shift = 0;
- GLuint max = MAX_DEPTH;
- while ((max & 0x80000000) == 0) {
- max = max << 1;
- shift++;
- }
+ GLint row;
for (row = 0; row < height; row++, y++) {
- GLdepth zspan[MAX_WIDTH];
- const GLdepth *zptr = gl_pixel_addr_in_image(&ctx->Unpack,
+ const GLuint *zptr = _mesa_image_address(&ctx->Unpack,
pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
- for (i=0;i<width;i++) {
- zspan[i] = zptr[i] >> shift;
- }
- gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
+ gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
}
}
else {
GLint row;
for (row = 0; row < height; row++, y++) {
GLdepth zspan[MAX_WIDTH];
- const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack,
+ const GLvoid *src = _mesa_image_address(&ctx->Unpack,
pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
_mesa_unpack_depth_span( ctx, drawWidth, zspan, type, src,
&ctx->Unpack, GL_TRUE );
return;
/* Fragment depth values */
- if (ctx->Depth.Test) {
+ if (ctx->Depth.Test || ctx->Fog.Enabled) {
/* fill in array of z values */
- GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
+ GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
GLint i;
for (i=0;i<width;i++) {
zspan[i] = z;
if (ctx->RasterMask == 0 && !zoom
&& x >= 0 && y >= 0
- && x + width <= ctx->Buffer->Width
- && y + height <= ctx->Buffer->Height) {
+ && x + width <= ctx->DrawBuffer->Width
+ && y + height <= ctx->DrawBuffer->Height) {
quickDraw = GL_TRUE;
}
else {
if (width > MAX_WIDTH)
width = MAX_WIDTH;
for (row = 0; row < height; row++, y++) {
- const GLvoid *source = gl_pixel_addr_in_image(unpack,
+ const GLvoid *source = _mesa_image_address(unpack,
pixels, width, height, format, type, 0, row, 0);
_mesa_unpack_ubyte_color_span(ctx, width, GL_RGBA, (void*) rgba,
format, type, source, unpack, GL_TRUE);
+ if (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink)
+ continue;
+
+ if (ctx->Texture.ReallyEnabled && ctx->Pixel.PixelTextureEnabled) {
+ GLfloat s[MAX_WIDTH], t[MAX_WIDTH], r[MAX_WIDTH], q[MAX_WIDTH];
+ GLuint unit;
+ /* XXX not sure how multitexture is supposed to work here */
+ for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++) {
+ _mesa_pixeltexgen(ctx, width, (const GLubyte (*)[4]) rgba,
+ s, t, r, q);
+ gl_texture_pixels(ctx, unit, width, s, t, r, NULL, rgba);
+ }
+ }
if (quickDraw) {
(*ctx->Driver.WriteRGBASpan)( ctx, width, x, y,
return;
}
+ if (ctx->NewState) {
+ gl_update_state(ctx);
+ }
+
x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
+ ctx->OcclusionResult = GL_TRUE;
+
+ /* see if device driver can do the drawpix */
+ if (ctx->Driver.DrawPixels
+ && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
+ &ctx->Unpack, pixels)) {
+ return;
+ }
+
switch (format) {
case GL_STENCIL_INDEX:
draw_stencil_pixels( ctx, x, y, width, height, type, pixels );
break;
case GL_COLOR_INDEX:
if (ctx->Visual->RGBAflag)
- draw_index_pixels(ctx, x, y, width, height, type, pixels);
- else
draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels);
+ else
+ draw_index_pixels(ctx, x, y, width, height, type, pixels);
break;
case GL_RED:
case GL_GREEN: