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