histogram.c revision c1f859d4
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.3
4 *
5 * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26#include "glheader.h"
27#include "bufferobj.h"
28#include "colormac.h"
29#include "context.h"
30#include "image.h"
31#include "histogram.h"
32
33
34
35/*
36 * XXX the packed pixel formats haven't been tested.
37 */
38static void
39pack_histogram( GLcontext *ctx,
40                GLuint n, CONST GLuint rgba[][4],
41                GLenum format, GLenum type, GLvoid *destination,
42                const struct gl_pixelstore_attrib *packing )
43{
44   const GLint comps = _mesa_components_in_format(format);
45   GLuint luminance[MAX_WIDTH];
46
47   if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) {
48      GLuint i;
49      for (i = 0; i < n; i++) {
50         luminance[i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
51      }
52   }
53
54#define PACK_MACRO(TYPE)					\
55   {								\
56      GLuint i;							\
57      switch (format) {						\
58         case GL_RED:						\
59            for (i=0;i<n;i++)					\
60               dst[i] = (TYPE) rgba[i][RCOMP];			\
61            break;						\
62         case GL_GREEN:						\
63            for (i=0;i<n;i++)					\
64               dst[i] = (TYPE) rgba[i][GCOMP];			\
65            break;						\
66         case GL_BLUE:						\
67            for (i=0;i<n;i++)					\
68               dst[i] = (TYPE) rgba[i][BCOMP];			\
69            break;						\
70         case GL_ALPHA:						\
71            for (i=0;i<n;i++)					\
72               dst[i] = (TYPE) rgba[i][ACOMP];			\
73            break;						\
74         case GL_LUMINANCE:					\
75            for (i=0;i<n;i++)					\
76               dst[i] = (TYPE) luminance[i];			\
77            break;						\
78         case GL_LUMINANCE_ALPHA:				\
79            for (i=0;i<n;i++) {					\
80               dst[i*2+0] = (TYPE) luminance[i];		\
81               dst[i*2+1] = (TYPE) rgba[i][ACOMP];		\
82            }							\
83            break;						\
84         case GL_RGB:						\
85            for (i=0;i<n;i++) {					\
86               dst[i*3+0] = (TYPE) rgba[i][RCOMP];		\
87               dst[i*3+1] = (TYPE) rgba[i][GCOMP];		\
88               dst[i*3+2] = (TYPE) rgba[i][BCOMP];		\
89            }							\
90            break;						\
91         case GL_RGBA:						\
92            for (i=0;i<n;i++) {					\
93               dst[i*4+0] = (TYPE) rgba[i][RCOMP];		\
94               dst[i*4+1] = (TYPE) rgba[i][GCOMP];		\
95               dst[i*4+2] = (TYPE) rgba[i][BCOMP];		\
96               dst[i*4+3] = (TYPE) rgba[i][ACOMP];		\
97            }							\
98            break;						\
99         case GL_BGR:						\
100            for (i=0;i<n;i++) {					\
101               dst[i*3+0] = (TYPE) rgba[i][BCOMP];		\
102               dst[i*3+1] = (TYPE) rgba[i][GCOMP];		\
103               dst[i*3+2] = (TYPE) rgba[i][RCOMP];		\
104            }							\
105            break;						\
106         case GL_BGRA:						\
107            for (i=0;i<n;i++) {					\
108               dst[i*4+0] = (TYPE) rgba[i][BCOMP];		\
109               dst[i*4+1] = (TYPE) rgba[i][GCOMP];		\
110               dst[i*4+2] = (TYPE) rgba[i][RCOMP];		\
111               dst[i*4+3] = (TYPE) rgba[i][ACOMP];		\
112            }							\
113            break;						\
114         case GL_ABGR_EXT:					\
115            for (i=0;i<n;i++) {					\
116               dst[i*4+0] = (TYPE) rgba[i][ACOMP];		\
117               dst[i*4+1] = (TYPE) rgba[i][BCOMP];		\
118               dst[i*4+2] = (TYPE) rgba[i][GCOMP];		\
119               dst[i*4+3] = (TYPE) rgba[i][RCOMP];		\
120            }							\
121            break;						\
122         default:						\
123            _mesa_problem(ctx, "bad format in pack_histogram");	\
124      }								\
125   }
126
127   switch (type) {
128      case GL_UNSIGNED_BYTE:
129         {
130            GLubyte *dst = (GLubyte *) destination;
131            PACK_MACRO(GLubyte);
132         }
133         break;
134      case GL_BYTE:
135         {
136            GLbyte *dst = (GLbyte *) destination;
137            PACK_MACRO(GLbyte);
138         }
139         break;
140      case GL_UNSIGNED_SHORT:
141         {
142            GLushort *dst = (GLushort *) destination;
143            PACK_MACRO(GLushort);
144            if (packing->SwapBytes) {
145               _mesa_swap2(dst, n * comps);
146            }
147         }
148         break;
149      case GL_SHORT:
150         {
151            GLshort *dst = (GLshort *) destination;
152            PACK_MACRO(GLshort);
153            if (packing->SwapBytes) {
154               _mesa_swap2((GLushort *) dst, n * comps);
155            }
156         }
157         break;
158      case GL_UNSIGNED_INT:
159         {
160            GLuint *dst = (GLuint *) destination;
161            PACK_MACRO(GLuint);
162            if (packing->SwapBytes) {
163               _mesa_swap4(dst, n * comps);
164            }
165         }
166         break;
167      case GL_INT:
168         {
169            GLint *dst = (GLint *) destination;
170            PACK_MACRO(GLint);
171            if (packing->SwapBytes) {
172               _mesa_swap4((GLuint *) dst, n * comps);
173            }
174         }
175         break;
176      case GL_FLOAT:
177         {
178            GLfloat *dst = (GLfloat *) destination;
179            PACK_MACRO(GLfloat);
180            if (packing->SwapBytes) {
181               _mesa_swap4((GLuint *) dst, n * comps);
182            }
183         }
184         break;
185      case GL_HALF_FLOAT_ARB:
186         {
187            /* temporarily store as GLuints */
188            GLuint temp[4*HISTOGRAM_TABLE_SIZE];
189            GLhalfARB *dst = (GLhalfARB *) destination;
190            GLuint i;
191            /* get GLuint values */
192            PACK_MACRO(GLuint);
193            /* convert to GLhalf */
194            for (i = 0; i < n * comps; i++) {
195               dst[i] = _mesa_float_to_half((GLfloat) temp[i]);
196            }
197            if (packing->SwapBytes) {
198               _mesa_swap2((GLushort *) dst, n * comps);
199            }
200         }
201         break;
202      case GL_UNSIGNED_BYTE_3_3_2:
203         if (format == GL_RGB) {
204            GLubyte *dst = (GLubyte *) destination;
205            GLuint i;
206            for (i = 0; i < n; i++) {
207               dst[i] = ((rgba[i][RCOMP] & 0x7) << 5)
208                      | ((rgba[i][GCOMP] & 0x7) << 2)
209                      | ((rgba[i][BCOMP] & 0x3)     );
210            }
211         }
212         else {
213            GLubyte *dst = (GLubyte *) destination;
214            GLuint i;
215            ASSERT(format == GL_BGR);
216            for (i = 0; i < n; i++) {
217               dst[i] = ((rgba[i][BCOMP] & 0x7) << 5)
218                      | ((rgba[i][GCOMP] & 0x7) << 2)
219                      | ((rgba[i][RCOMP] & 0x3)     );
220            }
221         }
222         break;
223      case GL_UNSIGNED_BYTE_2_3_3_REV:
224         if (format == GL_RGB) {
225            GLubyte *dst = (GLubyte *) destination;
226            GLuint i;
227            for (i = 0; i < n; i++) {
228               dst[i] = ((rgba[i][RCOMP] & 0x3) << 6)
229                      | ((rgba[i][GCOMP] & 0x7) << 3)
230                      | ((rgba[i][BCOMP] & 0x7)     );
231            }
232         }
233         else {
234            GLubyte *dst = (GLubyte *) destination;
235            GLuint i;
236            ASSERT(format == GL_BGR);
237            for (i = 0; i < n; i++) {
238               dst[i] = ((rgba[i][BCOMP] & 0x3) << 6)
239                      | ((rgba[i][GCOMP] & 0x7) << 3)
240                      | ((rgba[i][RCOMP] & 0x7)     );
241            }
242         }
243         break;
244      case GL_UNSIGNED_SHORT_5_6_5:
245         if (format == GL_RGB) {
246            GLushort *dst = (GLushort *) destination;
247            GLuint i;
248            for (i = 0; i < n; i++) {
249               dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
250                      | ((rgba[i][GCOMP] & 0x3f) <<  5)
251                      | ((rgba[i][BCOMP] & 0x1f)      );
252            }
253         }
254         else {
255            GLushort *dst = (GLushort *) destination;
256            GLuint i;
257            ASSERT(format == GL_BGR);
258            for (i = 0; i < n; i++) {
259               dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11)
260                      | ((rgba[i][GCOMP] & 0x3f) <<  5)
261                      | ((rgba[i][RCOMP] & 0x1f)      );
262            }
263         }
264         break;
265      case GL_UNSIGNED_SHORT_5_6_5_REV:
266         if (format == GL_RGB) {
267            GLushort *dst = (GLushort *) destination;
268            GLuint i;
269            for (i = 0; i < n; i++) {
270               dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11)
271                      | ((rgba[i][GCOMP] & 0x3f) <<  5)
272                      | ((rgba[i][RCOMP] & 0x1f)      );
273            }
274         }
275         else {
276            GLushort *dst = (GLushort *) destination;
277            GLuint i;
278            ASSERT(format == GL_BGR);
279            for (i = 0; i < n; i++) {
280               dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
281                      | ((rgba[i][GCOMP] & 0x3f) <<  5)
282                      | ((rgba[i][BCOMP] & 0x1f)      );
283            }
284         }
285         break;
286      case GL_UNSIGNED_SHORT_4_4_4_4:
287         if (format == GL_RGBA) {
288            GLushort *dst = (GLushort *) destination;
289            GLuint i;
290            for (i = 0; i < n; i++) {
291               dst[i] = ((rgba[i][RCOMP] & 0xf) << 12)
292                      | ((rgba[i][GCOMP] & 0xf) <<  8)
293                      | ((rgba[i][BCOMP] & 0xf) <<  4)
294                      | ((rgba[i][ACOMP] & 0xf)      );
295            }
296         }
297         else if (format == GL_BGRA) {
298            GLushort *dst = (GLushort *) destination;
299            GLuint i;
300            for (i = 0; i < n; i++) {
301               dst[i] = ((rgba[i][BCOMP] & 0xf) << 12)
302                      | ((rgba[i][GCOMP] & 0xf) <<  8)
303                      | ((rgba[i][RCOMP] & 0xf) <<  4)
304                      | ((rgba[i][ACOMP] & 0xf)      );
305            }
306         }
307         else {
308            GLushort *dst = (GLushort *) destination;
309            GLuint i;
310            ASSERT(format == GL_ABGR_EXT);
311            for (i = 0; i < n; i++) {
312               dst[i] = ((rgba[i][ACOMP] & 0xf) << 12)
313                      | ((rgba[i][BCOMP] & 0xf) <<  8)
314                      | ((rgba[i][GCOMP] & 0xf) <<  4)
315                      | ((rgba[i][RCOMP] & 0xf)      );
316            }
317         }
318         break;
319      case GL_UNSIGNED_SHORT_4_4_4_4_REV:
320         if (format == GL_RGBA) {
321            GLushort *dst = (GLushort *) destination;
322            GLuint i;
323            for (i = 0; i < n; i++) {
324               dst[i] = ((rgba[i][ACOMP] & 0xf) << 12)
325                      | ((rgba[i][BCOMP] & 0xf) <<  8)
326                      | ((rgba[i][GCOMP] & 0xf) <<  4)
327                      | ((rgba[i][RCOMP] & 0xf)      );
328            }
329         }
330         else if (format == GL_BGRA) {
331            GLushort *dst = (GLushort *) destination;
332            GLuint i;
333            for (i = 0; i < n; i++) {
334               dst[i] = ((rgba[i][ACOMP] & 0xf) << 12)
335                      | ((rgba[i][RCOMP] & 0xf) <<  8)
336                      | ((rgba[i][GCOMP] & 0xf) <<  4)
337                      | ((rgba[i][BCOMP] & 0xf)      );
338            }
339         }
340         else {
341            GLushort *dst = (GLushort *) destination;
342            GLuint i;
343            ASSERT(format == GL_ABGR_EXT);
344            for (i = 0; i < n; i++) {
345               dst[i] = ((rgba[i][RCOMP] & 0xf) << 12)
346                      | ((rgba[i][GCOMP] & 0xf) <<  8)
347                      | ((rgba[i][BCOMP] & 0xf) <<  4)
348                      | ((rgba[i][ACOMP] & 0xf)      );
349            }
350         }
351         break;
352      case GL_UNSIGNED_SHORT_5_5_5_1:
353         if (format == GL_RGBA) {
354            GLushort *dst = (GLushort *) destination;
355            GLuint i;
356            for (i = 0; i < n; i++) {
357               dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
358                      | ((rgba[i][GCOMP] & 0x1f) <<  6)
359                      | ((rgba[i][BCOMP] & 0x1f) <<  1)
360                      | ((rgba[i][ACOMP] & 0x1)       );
361            }
362         }
363         else if (format == GL_BGRA) {
364            GLushort *dst = (GLushort *) destination;
365            GLuint i;
366            for (i = 0; i < n; i++) {
367               dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11)
368                      | ((rgba[i][GCOMP] & 0x1f) <<  6)
369                      | ((rgba[i][RCOMP] & 0x1f) <<  1)
370                      | ((rgba[i][ACOMP] & 0x1)       );
371            }
372         }
373         else {
374            GLushort *dst = (GLushort *) destination;
375            GLuint i;
376            ASSERT(format == GL_ABGR_EXT);
377            for (i = 0; i < n; i++) {
378               dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11)
379                      | ((rgba[i][BCOMP] & 0x1f) <<  6)
380                      | ((rgba[i][GCOMP] & 0x1f) <<  1)
381                      | ((rgba[i][RCOMP] & 0x1)       );
382            }
383         }
384         break;
385      case GL_UNSIGNED_SHORT_1_5_5_5_REV:
386         if (format == GL_RGBA) {
387            GLushort *dst = (GLushort *) destination;
388            GLuint i;
389            for (i = 0; i < n; i++) {
390               dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11)
391                      | ((rgba[i][BCOMP] & 0x1f) <<  6)
392                      | ((rgba[i][GCOMP] & 0x1f) <<  1)
393                      | ((rgba[i][RCOMP] & 0x1)       );
394            }
395         }
396         else if (format == GL_BGRA) {
397            GLushort *dst = (GLushort *) destination;
398            GLuint i;
399            for (i = 0; i < n; i++) {
400               dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11)
401                      | ((rgba[i][RCOMP] & 0x1f) <<  6)
402                      | ((rgba[i][GCOMP] & 0x1f) <<  1)
403                      | ((rgba[i][BCOMP] & 0x1)       );
404            }
405         }
406         else {
407            GLushort *dst = (GLushort *) destination;
408            GLuint i;
409            ASSERT(format == GL_ABGR_EXT);
410            for (i = 0; i < n; i++) {
411               dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
412                      | ((rgba[i][GCOMP] & 0x1f) <<  6)
413                      | ((rgba[i][BCOMP] & 0x1f) <<  1)
414                      | ((rgba[i][ACOMP] & 0x1)       );
415            }
416         }
417         break;
418      case GL_UNSIGNED_INT_8_8_8_8:
419         if (format == GL_RGBA) {
420            GLuint *dst = (GLuint *) destination;
421            GLuint i;
422            for (i = 0; i < n; i++) {
423               dst[i] = ((rgba[i][RCOMP] & 0xff) << 24)
424                      | ((rgba[i][GCOMP] & 0xff) << 16)
425                      | ((rgba[i][BCOMP] & 0xff) <<  8)
426                      | ((rgba[i][ACOMP] & 0xff)      );
427            }
428         }
429         else if (format == GL_BGRA) {
430            GLuint *dst = (GLuint *) destination;
431            GLuint i;
432            for (i = 0; i < n; i++) {
433               dst[i] = ((rgba[i][BCOMP] & 0xff) << 24)
434                      | ((rgba[i][GCOMP] & 0xff) << 16)
435                      | ((rgba[i][RCOMP] & 0xff) <<  8)
436                      | ((rgba[i][ACOMP] & 0xff)      );
437            }
438         }
439         else {
440            GLuint *dst = (GLuint *) destination;
441            GLuint i;
442            ASSERT(format == GL_ABGR_EXT);
443            for (i = 0; i < n; i++) {
444               dst[i] = ((rgba[i][ACOMP] & 0xff) << 24)
445                      | ((rgba[i][BCOMP] & 0xff) << 16)
446                      | ((rgba[i][GCOMP] & 0xff) <<  8)
447                      | ((rgba[i][RCOMP] & 0xff)      );
448            }
449         }
450         break;
451      case GL_UNSIGNED_INT_8_8_8_8_REV:
452         if (format == GL_RGBA) {
453            GLuint *dst = (GLuint *) destination;
454            GLuint i;
455            for (i = 0; i < n; i++) {
456               dst[i] = ((rgba[i][ACOMP] & 0xff) << 24)
457                      | ((rgba[i][BCOMP] & 0xff) << 16)
458                      | ((rgba[i][GCOMP] & 0xff) <<  8)
459                      | ((rgba[i][RCOMP] & 0xff)      );
460            }
461         }
462         else if (format == GL_BGRA) {
463            GLuint *dst = (GLuint *) destination;
464            GLuint i;
465            for (i = 0; i < n; i++) {
466               dst[i] = ((rgba[i][ACOMP] & 0xff) << 24)
467                      | ((rgba[i][RCOMP] & 0xff) << 16)
468                      | ((rgba[i][GCOMP] & 0xff) <<  8)
469                      | ((rgba[i][BCOMP] & 0xff)      );
470            }
471         }
472         else {
473            GLuint *dst = (GLuint *) destination;
474            GLuint i;
475            ASSERT(format == GL_ABGR_EXT);
476            for (i = 0; i < n; i++) {
477               dst[i] = ((rgba[i][RCOMP] & 0xff) << 24)
478                      | ((rgba[i][GCOMP] & 0xff) << 16)
479                      | ((rgba[i][BCOMP] & 0xff) <<  8)
480                      | ((rgba[i][ACOMP] & 0xff)      );
481            }
482         }
483         break;
484      case GL_UNSIGNED_INT_10_10_10_2:
485         if (format == GL_RGBA) {
486            GLuint *dst = (GLuint *) destination;
487            GLuint i;
488            for (i = 0; i < n; i++) {
489               dst[i] = ((rgba[i][RCOMP] & 0x3ff) << 22)
490                      | ((rgba[i][GCOMP] & 0x3ff) << 12)
491                      | ((rgba[i][BCOMP] & 0x3ff) <<  2)
492                      | ((rgba[i][ACOMP] & 0x3)        );
493            }
494         }
495         else if (format == GL_BGRA) {
496            GLuint *dst = (GLuint *) destination;
497            GLuint i;
498            for (i = 0; i < n; i++) {
499               dst[i] = ((rgba[i][BCOMP] & 0x3ff) << 22)
500                      | ((rgba[i][GCOMP] & 0x3ff) << 12)
501                      | ((rgba[i][RCOMP] & 0x3ff) <<  2)
502                      | ((rgba[i][ACOMP] & 0x3)        );
503            }
504         }
505         else {
506            GLuint *dst = (GLuint *) destination;
507            GLuint i;
508            ASSERT(format == GL_ABGR_EXT);
509            for (i = 0; i < n; i++) {
510               dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22)
511                      | ((rgba[i][BCOMP] & 0x3ff) << 12)
512                      | ((rgba[i][GCOMP] & 0x3ff) <<  2)
513                      | ((rgba[i][RCOMP] & 0x3)        );
514            }
515         }
516         break;
517      case GL_UNSIGNED_INT_2_10_10_10_REV:
518         if (format == GL_RGBA) {
519            GLuint *dst = (GLuint *) destination;
520            GLuint i;
521            for (i = 0; i < n; i++) {
522               dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22)
523                      | ((rgba[i][BCOMP] & 0x3ff) << 12)
524                      | ((rgba[i][GCOMP] & 0x3ff) <<  2)
525                      | ((rgba[i][RCOMP] & 0x3)        );
526            }
527         }
528         else if (format == GL_BGRA) {
529            GLuint *dst = (GLuint *) destination;
530            GLuint i;
531            for (i = 0; i < n; i++) {
532               dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22)
533                      | ((rgba[i][RCOMP] & 0x3ff) << 12)
534                      | ((rgba[i][GCOMP] & 0x3ff) <<  2)
535                      | ((rgba[i][BCOMP] & 0x3)        );
536            }
537         }
538         else {
539            GLuint *dst = (GLuint *) destination;
540            GLuint i;
541            ASSERT(format == GL_ABGR_EXT);
542            for (i = 0; i < n; i++) {
543               dst[i] = ((rgba[i][RCOMP] & 0x3ff) << 22)
544                      | ((rgba[i][GCOMP] & 0x3ff) << 12)
545                      | ((rgba[i][BCOMP] & 0x3ff) <<  2)
546                      | ((rgba[i][ACOMP] & 0x3)        );
547            }
548         }
549         break;
550      default:
551         _mesa_problem(ctx, "Bad type in pack_histogram");
552   }
553
554#undef PACK_MACRO
555}
556
557
558/*
559 * Given an internalFormat token passed to glHistogram or glMinMax,
560 * return the corresponding base format.
561 * Return -1 if invalid token.
562 */
563static GLint
564base_histogram_format( GLenum format )
565{
566   switch (format) {
567      case GL_ALPHA:
568      case GL_ALPHA4:
569      case GL_ALPHA8:
570      case GL_ALPHA12:
571      case GL_ALPHA16:
572         return GL_ALPHA;
573      case GL_LUMINANCE:
574      case GL_LUMINANCE4:
575      case GL_LUMINANCE8:
576      case GL_LUMINANCE12:
577      case GL_LUMINANCE16:
578         return GL_LUMINANCE;
579      case GL_LUMINANCE_ALPHA:
580      case GL_LUMINANCE4_ALPHA4:
581      case GL_LUMINANCE6_ALPHA2:
582      case GL_LUMINANCE8_ALPHA8:
583      case GL_LUMINANCE12_ALPHA4:
584      case GL_LUMINANCE12_ALPHA12:
585      case GL_LUMINANCE16_ALPHA16:
586         return GL_LUMINANCE_ALPHA;
587      case GL_RGB:
588      case GL_R3_G3_B2:
589      case GL_RGB4:
590      case GL_RGB5:
591      case GL_RGB8:
592      case GL_RGB10:
593      case GL_RGB12:
594      case GL_RGB16:
595         return GL_RGB;
596      case GL_RGBA:
597      case GL_RGBA2:
598      case GL_RGBA4:
599      case GL_RGB5_A1:
600      case GL_RGBA8:
601      case GL_RGB10_A2:
602      case GL_RGBA12:
603      case GL_RGBA16:
604         return GL_RGBA;
605      default:
606         return -1;  /* error */
607   }
608}
609
610
611
612/**********************************************************************
613 * API functions
614 */
615
616
617void GLAPIENTRY
618_mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values)
619{
620   GET_CURRENT_CONTEXT(ctx);
621   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
622
623   if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
624      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmax");
625      return;
626   }
627
628   if (target != GL_MINMAX) {
629      _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinmax(target)");
630      return;
631   }
632
633   if (format != GL_RED &&
634       format != GL_GREEN &&
635       format != GL_BLUE &&
636       format != GL_ALPHA &&
637       format != GL_RGB &&
638       format != GL_BGR &&
639       format != GL_RGBA &&
640       format != GL_BGRA &&
641       format != GL_ABGR_EXT &&
642       format != GL_LUMINANCE &&
643       format != GL_LUMINANCE_ALPHA) {
644      _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinMax(format)");
645   }
646
647   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
648      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmax(format or type)");
649      return;
650   }
651
652   if (ctx->Pack.BufferObj->Name) {
653      /* pack min/max values into a PBO */
654      GLubyte *buf;
655      if (!_mesa_validate_pbo_access(1, &ctx->Pack, 2, 1, 1,
656                                     format, type, values)) {
657         _mesa_error(ctx, GL_INVALID_OPERATION,
658                     "glGetMinMax(invalid PBO access)");
659         return;
660      }
661      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
662                                              GL_WRITE_ONLY_ARB,
663                                              ctx->Pack.BufferObj);
664      if (!buf) {
665         /* buffer is already mapped - that's an error */
666         _mesa_error(ctx, GL_INVALID_OPERATION,"glGetMinMax(PBO is mapped)");
667         return;
668      }
669      values = ADD_POINTERS(buf, values);
670   }
671   else if (!values) {
672      /* not an error */
673      return;
674   }
675
676   {
677      GLfloat minmax[2][4];
678      minmax[0][RCOMP] = CLAMP(ctx->MinMax.Min[RCOMP], 0.0F, 1.0F);
679      minmax[0][GCOMP] = CLAMP(ctx->MinMax.Min[GCOMP], 0.0F, 1.0F);
680      minmax[0][BCOMP] = CLAMP(ctx->MinMax.Min[BCOMP], 0.0F, 1.0F);
681      minmax[0][ACOMP] = CLAMP(ctx->MinMax.Min[ACOMP], 0.0F, 1.0F);
682      minmax[1][RCOMP] = CLAMP(ctx->MinMax.Max[RCOMP], 0.0F, 1.0F);
683      minmax[1][GCOMP] = CLAMP(ctx->MinMax.Max[GCOMP], 0.0F, 1.0F);
684      minmax[1][BCOMP] = CLAMP(ctx->MinMax.Max[BCOMP], 0.0F, 1.0F);
685      minmax[1][ACOMP] = CLAMP(ctx->MinMax.Max[ACOMP], 0.0F, 1.0F);
686      _mesa_pack_rgba_span_float(ctx, 2, minmax,
687                                 format, type, values, &ctx->Pack, 0x0);
688   }
689
690   if (ctx->Pack.BufferObj->Name) {
691      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
692                              ctx->Pack.BufferObj);
693   }
694
695   if (reset) {
696      _mesa_ResetMinmax(GL_MINMAX);
697   }
698}
699
700
701void GLAPIENTRY
702_mesa_GetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values)
703{
704   GET_CURRENT_CONTEXT(ctx);
705   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
706
707   if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
708      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogram");
709      return;
710   }
711
712   if (target != GL_HISTOGRAM) {
713      _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogram(target)");
714      return;
715   }
716
717   if (format != GL_RED &&
718       format != GL_GREEN &&
719       format != GL_BLUE &&
720       format != GL_ALPHA &&
721       format != GL_RGB &&
722       format != GL_BGR &&
723       format != GL_RGBA &&
724       format != GL_BGRA &&
725       format != GL_ABGR_EXT &&
726       format != GL_LUMINANCE &&
727       format != GL_LUMINANCE_ALPHA) {
728      _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogram(format)");
729   }
730
731   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
732      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogram(format or type)");
733      return;
734   }
735
736   if (ctx->Pack.BufferObj->Name) {
737      /* pack min/max values into a PBO */
738      GLubyte *buf;
739      if (!_mesa_validate_pbo_access(1, &ctx->Pack, ctx->Histogram.Width, 1, 1,
740                                     format, type, values)) {
741         _mesa_error(ctx, GL_INVALID_OPERATION,
742                     "glGetHistogram(invalid PBO access)");
743         return;
744      }
745      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
746                                              GL_WRITE_ONLY_ARB,
747                                              ctx->Pack.BufferObj);
748      if (!buf) {
749         /* buffer is already mapped - that's an error */
750         _mesa_error(ctx,GL_INVALID_OPERATION,"glGetHistogram(PBO is mapped)");
751         return;
752      }
753      values = ADD_POINTERS(buf, values);
754   }
755   else if (!values) {
756      /* not an error */
757      return;
758   }
759
760   pack_histogram(ctx, ctx->Histogram.Width,
761                  (CONST GLuint (*)[4]) ctx->Histogram.Count,
762                  format, type, values, &ctx->Pack);
763
764   if (ctx->Pack.BufferObj->Name) {
765      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
766                              ctx->Pack.BufferObj);
767   }
768
769   if (reset) {
770      GLuint i;
771      for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
772         ctx->Histogram.Count[i][0] = 0;
773         ctx->Histogram.Count[i][1] = 0;
774         ctx->Histogram.Count[i][2] = 0;
775         ctx->Histogram.Count[i][3] = 0;
776      }
777   }
778}
779
780
781void GLAPIENTRY
782_mesa_GetHistogramParameterfv(GLenum target, GLenum pname, GLfloat *params)
783{
784   GET_CURRENT_CONTEXT(ctx);
785   ASSERT_OUTSIDE_BEGIN_END(ctx);
786
787   if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
788      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogramParameterfv");
789      return;
790   }
791
792   if (target != GL_HISTOGRAM && target != GL_PROXY_HISTOGRAM) {
793      _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameterfv(target)");
794      return;
795   }
796
797   switch (pname) {
798      case GL_HISTOGRAM_WIDTH:
799         *params = (GLfloat) ctx->Histogram.Width;
800         break;
801      case GL_HISTOGRAM_FORMAT:
802         *params = (GLfloat) ctx->Histogram.Format;
803         break;
804      case GL_HISTOGRAM_RED_SIZE:
805         *params = (GLfloat) ctx->Histogram.RedSize;
806         break;
807      case GL_HISTOGRAM_GREEN_SIZE:
808         *params = (GLfloat) ctx->Histogram.GreenSize;
809         break;
810      case GL_HISTOGRAM_BLUE_SIZE:
811         *params = (GLfloat) ctx->Histogram.BlueSize;
812         break;
813      case GL_HISTOGRAM_ALPHA_SIZE:
814         *params = (GLfloat) ctx->Histogram.AlphaSize;
815         break;
816      case GL_HISTOGRAM_LUMINANCE_SIZE:
817         *params = (GLfloat) ctx->Histogram.LuminanceSize;
818         break;
819      case GL_HISTOGRAM_SINK:
820         *params = (GLfloat) ctx->Histogram.Sink;
821         break;
822      default:
823         _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameterfv(pname)");
824   }
825}
826
827
828void GLAPIENTRY
829_mesa_GetHistogramParameteriv(GLenum target, GLenum pname, GLint *params)
830{
831   GET_CURRENT_CONTEXT(ctx);
832   ASSERT_OUTSIDE_BEGIN_END(ctx);
833
834   if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
835      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogramParameteriv");
836      return;
837   }
838
839   if (target != GL_HISTOGRAM && target != GL_PROXY_HISTOGRAM) {
840      _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameteriv(target)");
841      return;
842   }
843
844   switch (pname) {
845      case GL_HISTOGRAM_WIDTH:
846         *params = (GLint) ctx->Histogram.Width;
847         break;
848      case GL_HISTOGRAM_FORMAT:
849         *params = (GLint) ctx->Histogram.Format;
850         break;
851      case GL_HISTOGRAM_RED_SIZE:
852         *params = (GLint) ctx->Histogram.RedSize;
853         break;
854      case GL_HISTOGRAM_GREEN_SIZE:
855         *params = (GLint) ctx->Histogram.GreenSize;
856         break;
857      case GL_HISTOGRAM_BLUE_SIZE:
858         *params = (GLint) ctx->Histogram.BlueSize;
859         break;
860      case GL_HISTOGRAM_ALPHA_SIZE:
861         *params = (GLint) ctx->Histogram.AlphaSize;
862         break;
863      case GL_HISTOGRAM_LUMINANCE_SIZE:
864         *params = (GLint) ctx->Histogram.LuminanceSize;
865         break;
866      case GL_HISTOGRAM_SINK:
867         *params = (GLint) ctx->Histogram.Sink;
868         break;
869      default:
870         _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameteriv(pname)");
871   }
872}
873
874
875void GLAPIENTRY
876_mesa_GetMinmaxParameterfv(GLenum target, GLenum pname, GLfloat *params)
877{
878   GET_CURRENT_CONTEXT(ctx);
879   ASSERT_OUTSIDE_BEGIN_END(ctx);
880
881   if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
882      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmaxParameterfv");
883      return;
884   }
885   if (target != GL_MINMAX) {
886      _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinmaxParameterfv(target)");
887      return;
888   }
889   if (pname == GL_MINMAX_FORMAT) {
890      *params = (GLfloat) ctx->MinMax.Format;
891   }
892   else if (pname == GL_MINMAX_SINK) {
893      *params = (GLfloat) ctx->MinMax.Sink;
894   }
895   else {
896      _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinMaxParameterfv(pname)");
897   }
898}
899
900
901void GLAPIENTRY
902_mesa_GetMinmaxParameteriv(GLenum target, GLenum pname, GLint *params)
903{
904   GET_CURRENT_CONTEXT(ctx);
905   ASSERT_OUTSIDE_BEGIN_END(ctx);
906
907   if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
908      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmaxParameteriv");
909      return;
910   }
911   if (target != GL_MINMAX) {
912      _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinmaxParameteriv(target)");
913      return;
914   }
915   if (pname == GL_MINMAX_FORMAT) {
916      *params = (GLint) ctx->MinMax.Format;
917   }
918   else if (pname == GL_MINMAX_SINK) {
919      *params = (GLint) ctx->MinMax.Sink;
920   }
921   else {
922      _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinMaxParameteriv(pname)");
923   }
924}
925
926
927void GLAPIENTRY
928_mesa_Histogram(GLenum target, GLsizei width, GLenum internalFormat, GLboolean sink)
929{
930   GLuint i;
931   GLboolean error = GL_FALSE;
932   GET_CURRENT_CONTEXT(ctx);
933   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* sideeffects */
934
935   if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
936      _mesa_error(ctx, GL_INVALID_OPERATION, "glHistogram");
937      return;
938   }
939
940   if (target != GL_HISTOGRAM && target != GL_PROXY_HISTOGRAM) {
941      _mesa_error(ctx, GL_INVALID_ENUM, "glHistogram(target)");
942      return;
943   }
944
945   if (width < 0 || width > HISTOGRAM_TABLE_SIZE) {
946      if (target == GL_PROXY_HISTOGRAM) {
947         error = GL_TRUE;
948      }
949      else {
950         if (width < 0)
951            _mesa_error(ctx, GL_INVALID_VALUE, "glHistogram(width)");
952         else
953            _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glHistogram(width)");
954         return;
955      }
956   }
957
958   if (width != 0 && !_mesa_is_pow_two(width)) {
959      if (target == GL_PROXY_HISTOGRAM) {
960         error = GL_TRUE;
961      }
962      else {
963         _mesa_error(ctx, GL_INVALID_VALUE, "glHistogram(width)");
964         return;
965      }
966   }
967
968   if (base_histogram_format(internalFormat) < 0) {
969      if (target == GL_PROXY_HISTOGRAM) {
970         error = GL_TRUE;
971      }
972      else {
973         _mesa_error(ctx, GL_INVALID_ENUM, "glHistogram(internalFormat)");
974         return;
975      }
976   }
977
978   /* reset histograms */
979   for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
980      ctx->Histogram.Count[i][0] = 0;
981      ctx->Histogram.Count[i][1] = 0;
982      ctx->Histogram.Count[i][2] = 0;
983      ctx->Histogram.Count[i][3] = 0;
984   }
985
986   if (error) {
987      ctx->Histogram.Width = 0;
988      ctx->Histogram.Format = 0;
989      ctx->Histogram.RedSize       = 0;
990      ctx->Histogram.GreenSize     = 0;
991      ctx->Histogram.BlueSize      = 0;
992      ctx->Histogram.AlphaSize     = 0;
993      ctx->Histogram.LuminanceSize = 0;
994   }
995   else {
996      ctx->Histogram.Width = width;
997      ctx->Histogram.Format = internalFormat;
998      ctx->Histogram.Sink = sink;
999      ctx->Histogram.RedSize       = 8 * sizeof(GLuint);
1000      ctx->Histogram.GreenSize     = 8 * sizeof(GLuint);
1001      ctx->Histogram.BlueSize      = 8 * sizeof(GLuint);
1002      ctx->Histogram.AlphaSize     = 8 * sizeof(GLuint);
1003      ctx->Histogram.LuminanceSize = 8 * sizeof(GLuint);
1004   }
1005
1006   ctx->NewState |= _NEW_PIXEL;
1007}
1008
1009
1010void GLAPIENTRY
1011_mesa_Minmax(GLenum target, GLenum internalFormat, GLboolean sink)
1012{
1013   GET_CURRENT_CONTEXT(ctx);
1014   ASSERT_OUTSIDE_BEGIN_END(ctx);
1015
1016   if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
1017      _mesa_error(ctx, GL_INVALID_OPERATION, "glMinmax");
1018      return;
1019   }
1020
1021   if (target != GL_MINMAX) {
1022      _mesa_error(ctx, GL_INVALID_ENUM, "glMinMax(target)");
1023      return;
1024   }
1025
1026   if (base_histogram_format(internalFormat) < 0) {
1027      _mesa_error(ctx, GL_INVALID_ENUM, "glMinMax(internalFormat)");
1028      return;
1029   }
1030
1031   if (ctx->MinMax.Sink == sink)
1032      return;
1033   FLUSH_VERTICES(ctx, _NEW_PIXEL);
1034   ctx->MinMax.Sink = sink;
1035}
1036
1037
1038void GLAPIENTRY
1039_mesa_ResetHistogram(GLenum target)
1040{
1041   GLuint i;
1042   GET_CURRENT_CONTEXT(ctx);
1043   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* sideeffects */
1044
1045   if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
1046      _mesa_error(ctx, GL_INVALID_OPERATION, "glResetHistogram");
1047      return;
1048   }
1049
1050   if (target != GL_HISTOGRAM) {
1051      _mesa_error(ctx, GL_INVALID_ENUM, "glResetHistogram(target)");
1052      return;
1053   }
1054
1055   for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
1056      ctx->Histogram.Count[i][0] = 0;
1057      ctx->Histogram.Count[i][1] = 0;
1058      ctx->Histogram.Count[i][2] = 0;
1059      ctx->Histogram.Count[i][3] = 0;
1060   }
1061
1062   ctx->NewState |= _NEW_PIXEL;
1063}
1064
1065
1066void GLAPIENTRY
1067_mesa_ResetMinmax(GLenum target)
1068{
1069   GET_CURRENT_CONTEXT(ctx);
1070   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1071
1072   if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
1073      _mesa_error(ctx, GL_INVALID_OPERATION, "glResetMinmax");
1074      return;
1075   }
1076
1077   if (target != GL_MINMAX) {
1078      _mesa_error(ctx, GL_INVALID_ENUM, "glResetMinMax(target)");
1079      return;
1080   }
1081
1082   ctx->MinMax.Min[RCOMP] = 1000;    ctx->MinMax.Max[RCOMP] = -1000;
1083   ctx->MinMax.Min[GCOMP] = 1000;    ctx->MinMax.Max[GCOMP] = -1000;
1084   ctx->MinMax.Min[BCOMP] = 1000;    ctx->MinMax.Max[BCOMP] = -1000;
1085   ctx->MinMax.Min[ACOMP] = 1000;    ctx->MinMax.Max[ACOMP] = -1000;
1086   ctx->NewState |= _NEW_PIXEL;
1087}
1088
1089
1090
1091/**********************************************************************/
1092/*****                      Initialization                        *****/
1093/**********************************************************************/
1094
1095void _mesa_init_histogram( GLcontext * ctx )
1096{
1097   int i;
1098
1099   /* Histogram group */
1100   ctx->Histogram.Width = 0;
1101   ctx->Histogram.Format = GL_RGBA;
1102   ctx->Histogram.Sink = GL_FALSE;
1103   ctx->Histogram.RedSize       = 0;
1104   ctx->Histogram.GreenSize     = 0;
1105   ctx->Histogram.BlueSize      = 0;
1106   ctx->Histogram.AlphaSize     = 0;
1107   ctx->Histogram.LuminanceSize = 0;
1108   for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
1109      ctx->Histogram.Count[i][0] = 0;
1110      ctx->Histogram.Count[i][1] = 0;
1111      ctx->Histogram.Count[i][2] = 0;
1112      ctx->Histogram.Count[i][3] = 0;
1113   }
1114
1115   /* Min/Max group */
1116   ctx->MinMax.Format = GL_RGBA;
1117   ctx->MinMax.Sink = GL_FALSE;
1118   ctx->MinMax.Min[RCOMP] = 1000;    ctx->MinMax.Max[RCOMP] = -1000;
1119   ctx->MinMax.Min[GCOMP] = 1000;    ctx->MinMax.Max[GCOMP] = -1000;
1120   ctx->MinMax.Min[BCOMP] = 1000;    ctx->MinMax.Max[BCOMP] = -1000;
1121   ctx->MinMax.Min[ACOMP] = 1000;    ctx->MinMax.Max[ACOMP] = -1000;
1122}
1123