-/* $Id: histogram.c,v 1.10 2001/03/12 00:48:38 gareth Exp $ */
-
/*
* Mesa 3-D graphics library
- * Version: 3.5
+ * Version: 6.3
*
- * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2004 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"),
*/
-#ifdef PC_HEADER
-#include "all.h"
-#else
#include "glheader.h"
+#include "bufferobj.h"
#include "colormac.h"
#include "context.h"
#include "image.h"
#include "histogram.h"
-#include "mmath.h"
-#endif
+
+
+/**********************************************************************
+ * Internal functions
+ */
+
+
+/*
+ * Update the min/max values from an array of fragment colors.
+ */
+void
+_mesa_update_minmax(GLcontext *ctx, GLuint n, const GLfloat rgba[][4])
+{
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ /* update mins */
+ if (rgba[i][RCOMP] < ctx->MinMax.Min[RCOMP])
+ ctx->MinMax.Min[RCOMP] = rgba[i][RCOMP];
+ if (rgba[i][GCOMP] < ctx->MinMax.Min[GCOMP])
+ ctx->MinMax.Min[GCOMP] = rgba[i][GCOMP];
+ if (rgba[i][BCOMP] < ctx->MinMax.Min[BCOMP])
+ ctx->MinMax.Min[BCOMP] = rgba[i][BCOMP];
+ if (rgba[i][ACOMP] < ctx->MinMax.Min[ACOMP])
+ ctx->MinMax.Min[ACOMP] = rgba[i][ACOMP];
+
+ /* update maxs */
+ if (rgba[i][RCOMP] > ctx->MinMax.Max[RCOMP])
+ ctx->MinMax.Max[RCOMP] = rgba[i][RCOMP];
+ if (rgba[i][GCOMP] > ctx->MinMax.Max[GCOMP])
+ ctx->MinMax.Max[GCOMP] = rgba[i][GCOMP];
+ if (rgba[i][BCOMP] > ctx->MinMax.Max[BCOMP])
+ ctx->MinMax.Max[BCOMP] = rgba[i][BCOMP];
+ if (rgba[i][ACOMP] > ctx->MinMax.Max[ACOMP])
+ ctx->MinMax.Max[ACOMP] = rgba[i][ACOMP];
+ }
+}
+
+
+/*
+ * Update the histogram values from an array of fragment colors.
+ */
+void
+_mesa_update_histogram(GLcontext *ctx, GLuint n, const GLfloat rgba[][4])
+{
+ const GLint max = ctx->Histogram.Width - 1;
+ GLfloat w = (GLfloat) max;
+ GLuint i;
+
+ if (ctx->Histogram.Width == 0)
+ return;
+
+ for (i = 0; i < n; i++) {
+ GLint ri = IROUND(rgba[i][RCOMP] * w);
+ GLint gi = IROUND(rgba[i][GCOMP] * w);
+ GLint bi = IROUND(rgba[i][BCOMP] * w);
+ GLint ai = IROUND(rgba[i][ACOMP] * w);
+ ri = CLAMP(ri, 0, max);
+ gi = CLAMP(gi, 0, max);
+ bi = CLAMP(bi, 0, max);
+ ai = CLAMP(ai, 0, max);
+ ctx->Histogram.Count[ri][RCOMP]++;
+ ctx->Histogram.Count[gi][GCOMP]++;
+ ctx->Histogram.Count[bi][BCOMP]++;
+ ctx->Histogram.Count[ai][ACOMP]++;
+ }
+}
/*
}
}
break;
+ case GL_HALF_FLOAT_ARB:
+ {
+ /* temporarily store as GLuints */
+ GLuint temp[4*HISTOGRAM_TABLE_SIZE];
+ GLhalfARB *dst = (GLhalfARB *) destination;
+ GLuint i;
+ /* get GLuint values */
+ PACK_MACRO(GLuint);
+ /* convert to GLhalf */
+ for (i = 0; i < n * comps; i++) {
+ dst[i] = _mesa_float_to_half((GLfloat) temp[i]);
+ }
+ if (packing->SwapBytes) {
+ _mesa_swap2((GLushort *) dst, n * comps);
+ }
+ }
+ break;
case GL_UNSIGNED_BYTE_3_3_2:
if (format == GL_RGB) {
GLubyte *dst = (GLubyte *) destination;
}
-void
+
+/**********************************************************************
+ * API functions
+ */
+
+
+void GLAPIENTRY
_mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values)
{
GET_CURRENT_CONTEXT(ctx);
return;
}
- if (!_mesa_is_legal_format_and_type(format, type)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmax(format or type)");
- return;
+ if (format != GL_RED &&
+ format != GL_GREEN &&
+ format != GL_BLUE &&
+ format != GL_ALPHA &&
+ format != GL_RGB &&
+ format != GL_BGR &&
+ format != GL_RGBA &&
+ format != GL_BGRA &&
+ format != GL_ABGR_EXT &&
+ format != GL_LUMINANCE &&
+ format != GL_LUMINANCE_ALPHA) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinMax(format)");
}
- if (type != GL_UNSIGNED_BYTE &&
- type != GL_BYTE &&
- type != GL_UNSIGNED_SHORT &&
- type != GL_SHORT &&
- type != GL_UNSIGNED_INT &&
- type != GL_INT &&
- type != GL_FLOAT &&
- type != GL_UNSIGNED_BYTE_3_3_2 &&
- type != GL_UNSIGNED_BYTE_2_3_3_REV &&
- type != GL_UNSIGNED_SHORT_5_6_5 &&
- type != GL_UNSIGNED_SHORT_5_6_5_REV &&
- type != GL_UNSIGNED_SHORT_4_4_4_4 &&
- type != GL_UNSIGNED_SHORT_4_4_4_4_REV &&
- type != GL_UNSIGNED_SHORT_5_5_5_1 &&
- type != GL_UNSIGNED_SHORT_1_5_5_5_REV &&
- type != GL_UNSIGNED_INT_8_8_8_8 &&
- type != GL_UNSIGNED_INT_8_8_8_8_REV &&
- type != GL_UNSIGNED_INT_10_10_10_2 &&
- type != GL_UNSIGNED_INT_2_10_10_10_REV) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinmax(type)");
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmax(format or type)");
return;
}
- if (!values)
+ if (ctx->Pack.BufferObj->Name) {
+ /* pack min/max values into a PBO */
+ GLubyte *buf;
+ if (!_mesa_validate_pbo_access(1, &ctx->Pack, 2, 1, 1,
+ format, type, values)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetMinMax(invalid PBO access)");
+ return;
+ }
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB,
+ ctx->Pack.BufferObj);
+ if (!buf) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,"glGetMinMax(PBO is mapped)");
+ return;
+ }
+ values = ADD_POINTERS(buf, values);
+ }
+ else if (!values) {
+ /* not an error */
return;
+ }
{
GLfloat minmax[2][4];
minmax[1][GCOMP] = CLAMP(ctx->MinMax.Max[GCOMP], 0.0F, 1.0F);
minmax[1][BCOMP] = CLAMP(ctx->MinMax.Max[BCOMP], 0.0F, 1.0F);
minmax[1][ACOMP] = CLAMP(ctx->MinMax.Max[ACOMP], 0.0F, 1.0F);
- _mesa_pack_float_rgba_span(ctx, 2, (CONST GLfloat (*)[4]) minmax,
+ _mesa_pack_rgba_span_float(ctx, 2, (CONST GLfloat (*)[4]) minmax,
format, type, values, &ctx->Pack, 0);
}
+ if (ctx->Pack.BufferObj->Name) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ ctx->Pack.BufferObj);
+ }
+
if (reset) {
_mesa_ResetMinmax(GL_MINMAX);
}
}
-void
+void GLAPIENTRY
_mesa_GetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values)
{
GET_CURRENT_CONTEXT(ctx);
return;
}
- if (!_mesa_is_legal_format_and_type(format, type)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogram(format or type)");
- return;
+ if (format != GL_RED &&
+ format != GL_GREEN &&
+ format != GL_BLUE &&
+ format != GL_ALPHA &&
+ format != GL_RGB &&
+ format != GL_BGR &&
+ format != GL_RGBA &&
+ format != GL_BGRA &&
+ format != GL_ABGR_EXT &&
+ format != GL_LUMINANCE &&
+ format != GL_LUMINANCE_ALPHA) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogram(format)");
}
- if (type != GL_UNSIGNED_BYTE &&
- type != GL_BYTE &&
- type != GL_UNSIGNED_SHORT &&
- type != GL_SHORT &&
- type != GL_UNSIGNED_INT &&
- type != GL_INT &&
- type != GL_FLOAT &&
- type != GL_UNSIGNED_BYTE_3_3_2 &&
- type != GL_UNSIGNED_BYTE_2_3_3_REV &&
- type != GL_UNSIGNED_SHORT_5_6_5 &&
- type != GL_UNSIGNED_SHORT_5_6_5_REV &&
- type != GL_UNSIGNED_SHORT_4_4_4_4 &&
- type != GL_UNSIGNED_SHORT_4_4_4_4_REV &&
- type != GL_UNSIGNED_SHORT_5_5_5_1 &&
- type != GL_UNSIGNED_SHORT_1_5_5_5_REV &&
- type != GL_UNSIGNED_INT_8_8_8_8 &&
- type != GL_UNSIGNED_INT_8_8_8_8_REV &&
- type != GL_UNSIGNED_INT_10_10_10_2 &&
- type != GL_UNSIGNED_INT_2_10_10_10_REV) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogram(type)");
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogram(format or type)");
return;
}
- if (!values)
+ if (ctx->Pack.BufferObj->Name) {
+ /* pack min/max values into a PBO */
+ GLubyte *buf;
+ if (!_mesa_validate_pbo_access(1, &ctx->Pack, ctx->Histogram.Width, 1, 1,
+ format, type, values)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetHistogram(invalid PBO access)");
+ return;
+ }
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB,
+ ctx->Pack.BufferObj);
+ if (!buf) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx,GL_INVALID_OPERATION,"glGetHistogram(PBO is mapped)");
+ return;
+ }
+ values = ADD_POINTERS(buf, values);
+ }
+ else if (!values) {
+ /* not an error */
return;
+ }
pack_histogram(ctx, ctx->Histogram.Width,
(CONST GLuint (*)[4]) ctx->Histogram.Count,
format, type, values, &ctx->Pack);
+ if (ctx->Pack.BufferObj->Name) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ ctx->Pack.BufferObj);
+ }
+
if (reset) {
GLuint i;
for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
}
-void
+void GLAPIENTRY
_mesa_GetHistogramParameterfv(GLenum target, GLenum pname, GLfloat *params)
{
GET_CURRENT_CONTEXT(ctx);
}
-void
+void GLAPIENTRY
_mesa_GetHistogramParameteriv(GLenum target, GLenum pname, GLint *params)
{
GET_CURRENT_CONTEXT(ctx);
}
-void
+void GLAPIENTRY
_mesa_GetMinmaxParameterfv(GLenum target, GLenum pname, GLfloat *params)
{
GET_CURRENT_CONTEXT(ctx);
}
-void
+void GLAPIENTRY
_mesa_GetMinmaxParameteriv(GLenum target, GLenum pname, GLint *params)
{
GET_CURRENT_CONTEXT(ctx);
}
-void
+void GLAPIENTRY
_mesa_Histogram(GLenum target, GLsizei width, GLenum internalFormat, GLboolean sink)
{
GLuint i;
}
-void
+void GLAPIENTRY
_mesa_Minmax(GLenum target, GLenum internalFormat, GLboolean sink)
{
GET_CURRENT_CONTEXT(ctx);
}
-void
+void GLAPIENTRY
_mesa_ResetHistogram(GLenum target)
{
GLuint i;
}
-void
+void GLAPIENTRY
_mesa_ResetMinmax(GLenum target)
{
GET_CURRENT_CONTEXT(ctx);
ctx->MinMax.Min[ACOMP] = 1000; ctx->MinMax.Max[ACOMP] = -1000;
ctx->NewState |= _NEW_PIXEL;
}
+
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+void _mesa_init_histogram( GLcontext * ctx )
+{
+ int i;
+
+ /* Histogram group */
+ ctx->Histogram.Width = 0;
+ ctx->Histogram.Format = GL_RGBA;
+ ctx->Histogram.Sink = GL_FALSE;
+ ctx->Histogram.RedSize = 0;
+ ctx->Histogram.GreenSize = 0;
+ ctx->Histogram.BlueSize = 0;
+ ctx->Histogram.AlphaSize = 0;
+ ctx->Histogram.LuminanceSize = 0;
+ for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
+ ctx->Histogram.Count[i][0] = 0;
+ ctx->Histogram.Count[i][1] = 0;
+ ctx->Histogram.Count[i][2] = 0;
+ ctx->Histogram.Count[i][3] = 0;
+ }
+
+ /* Min/Max group */
+ ctx->MinMax.Format = GL_RGBA;
+ ctx->MinMax.Sink = GL_FALSE;
+ ctx->MinMax.Min[RCOMP] = 1000; ctx->MinMax.Max[RCOMP] = -1000;
+ ctx->MinMax.Min[GCOMP] = 1000; ctx->MinMax.Max[GCOMP] = -1000;
+ ctx->MinMax.Min[BCOMP] = 1000; ctx->MinMax.Max[BCOMP] = -1000;
+ ctx->MinMax.Min[ACOMP] = 1000; ctx->MinMax.Max[ACOMP] = -1000;
+}