Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
55 pj 1
/* $Id: texutil.c,v 1.1 2003-02-28 11:42:06 pj Exp $ */
2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  4.1
6
 *
7
 * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included
17
 * in all copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 * Authors:
27
 *    Gareth Hughes
28
 */
29
 
30
/*
31
 * Description:
32
 * Functions for texture image conversion.  This takes care of converting
33
 * typical GL_RGBA/GLubyte textures into hardware-specific formats.
34
 * We can handle non-standard row strides and pixel unpacking parameters.
35
 */
36
 
37
 
38
#include "glheader.h"
39
#include "context.h"
40
#include "enums.h"
41
#include "image.h"
42
#include "imports.h"
43
#include "macros.h"
44
#include "mtypes.h"
45
#include "texformat.h"
46
#include "texutil.h"
47
 
48
 
49
#define DEBUG_TEXUTIL 0
50
 
51
 
52
#ifdef MESA_BIG_ENDIAN
53
#define APPEND16( a, b )        ( (a) << 16 | (b) )
54
#else
55
#define APPEND16( a, b )        ( (a) | (b) << 16 )
56
#endif
57
 
58
 
59
struct convert_info {
60
   GLint xoffset, yoffset, zoffset;     /* Subimage offset */
61
   GLint width, height, depth;          /* Subimage region */
62
 
63
   GLint dstImageWidth, dstImageHeight; /* Dest image size */
64
                                        /* Needed for subimage replacement */
65
   GLenum format, type;                 /* Source (user) format and type */
66
 
67
   const struct gl_pixelstore_attrib *unpacking;
68
 
69
   const GLvoid *srcImage;
70
   GLvoid *dstImage;
71
 
72
   GLint index;
73
};
74
 
75
typedef GLboolean (*convert_func)( const struct convert_info *convert );
76
 
77
/* bitvalues for convert->index */
78
#define CONVERT_STRIDE_BIT      0x1
79
#define CONVERT_UNPACKING_BIT   0x2
80
 
81
 
82
 
83
/* =============================================================
84
 * Convert to RGBA8888 textures:
85
 */
86
 
87
#define DST_TYPE                GLuint
88
#define DST_TEXELS_PER_DWORD    1
89
 
90
#define CONVERT_TEXEL( dst, src )                                       \
91
        dst = PACK_COLOR_8888_LE( src[3], src[2], src[1], src[0] )
92
 
93
#define CONVERT_DIRECT
94
 
95
#define SRC_TEXEL_BYTES         4
96
 
97
#define TAG(x) x##_rgba8888_direct
98
#define PRESERVE_DST_TYPE
99
#include "texutil_tmp.h"
100
 
101
 
102
#define CONVERT_TEXEL( dst, src )                                       \
103
        dst = PACK_COLOR_8888_LE( src[0], src[1], src[2], src[3] )
104
 
105
#define CONVERT_TEXEL_DWORD( dst, src )         CONVERT_TEXEL( dst, src )
106
 
107
#define SRC_TEXEL_BYTES         4
108
 
109
#define TAG(x) x##_abgr8888_to_rgba8888
110
#define PRESERVE_DST_TYPE
111
#include "texutil_tmp.h"
112
 
113
 
114
#define CONVERT_TEXEL( dst, src )                                       \
115
        dst = PACK_COLOR_8888_LE( src[0], src[1], src[2], 0xff )
116
 
117
#define CONVERT_TEXEL_DWORD( dst, src )         CONVERT_TEXEL( dst, src )
118
 
119
#define SRC_TEXEL_BYTES         3
120
 
121
#define TAG(x) x##_bgr888_to_rgba8888
122
#include "texutil_tmp.h"
123
 
124
 
125
#define CONVERT_RGBA8888( name )                                        \
126
static GLboolean                                                        \
127
convert_##name##_rgba8888( const struct convert_info *convert )         \
128
{                                                                       \
129
   convert_func *tab;                                                   \
130
   GLint index = convert->index;                                        \
131
                                                                        \
132
   if ( convert->format == GL_ABGR_EXT &&                               \
133
        convert->type == GL_UNSIGNED_INT_8_8_8_8_REV )                  \
134
   {                                                                    \
135
      tab = name##_tab_rgba8888_direct;                                 \
136
   }                                                                    \
137
   else if ( convert->format == GL_RGBA &&                              \
138
             ( convert->type == GL_UNSIGNED_BYTE ||                     \
139
               convert->type == GL_UNSIGNED_INT_8_8_8_8 ) )             \
140
   {                                                                    \
141
      tab = name##_tab_abgr8888_to_rgba8888;                            \
142
   }                                                                    \
143
   else if ( convert->format == GL_RGB &&                               \
144
             convert->type == GL_UNSIGNED_BYTE )                        \
145
   {                                                                    \
146
      tab = name##_tab_bgr888_to_rgba8888;                              \
147
   }                                                                    \
148
   else                                                                 \
149
   {                                                                    \
150
      /* Can't handle this source format/type combination */            \
151
      return GL_FALSE;                                                  \
152
   }                                                                    \
153
                                                                        \
154
   return tab[index]( convert );                                        \
155
}
156
 
157
CONVERT_RGBA8888( texsubimage2d )
158
CONVERT_RGBA8888( texsubimage3d )
159
 
160
 
161
 
162
/* =============================================================
163
 * Convert to ARGB8888 textures:
164
 */
165
 
166
#define DST_TYPE                GLuint
167
#define DST_TEXELS_PER_DWORD    1
168
 
169
#define CONVERT_TEXEL( dst, src )                                       \
170
        dst = PACK_COLOR_8888_LE( src[3], src[2], src[1], src[0] )
171
 
172
#define CONVERT_DIRECT
173
 
174
#define SRC_TEXEL_BYTES         4
175
 
176
#define TAG(x) x##_argb8888_direct
177
#define PRESERVE_DST_TYPE
178
#include "texutil_tmp.h"
179
 
180
 
181
#define CONVERT_TEXEL( dst, src )                                       \
182
        dst = PACK_COLOR_8888_LE( src[3], src[0], src[1], src[2] )
183
 
184
#define CONVERT_TEXEL_DWORD( dst, src )         CONVERT_TEXEL( dst, src )
185
 
186
#define SRC_TEXEL_BYTES         4
187
 
188
#define TAG(x) x##_abgr8888_to_argb8888
189
#define PRESERVE_DST_TYPE
190
#include "texutil_tmp.h"
191
 
192
 
193
#define CONVERT_TEXEL( dst, src )                                       \
194
        dst = PACK_COLOR_8888_LE( 0xff, src[0], src[1], src[2] )
195
 
196
#define CONVERT_TEXEL_DWORD( dst, src )         CONVERT_TEXEL( dst, src )
197
 
198
#define SRC_TEXEL_BYTES         3
199
 
200
#define TAG(x) x##_bgr888_to_argb8888
201
#include "texutil_tmp.h"
202
 
203
 
204
#define CONVERT_ARGB8888( name )                                        \
205
static GLboolean                                                        \
206
convert_##name##_argb8888( const struct convert_info *convert )         \
207
{                                                                       \
208
   convert_func *tab;                                                   \
209
   GLint index = convert->index;                                        \
210
                                                                        \
211
   if ( convert->format == GL_BGRA &&                                   \
212
        convert->type == GL_UNSIGNED_INT_8_8_8_8_REV )                  \
213
   {                                                                    \
214
      tab = name##_tab_argb8888_direct;                                 \
215
   }                                                                    \
216
   else if ( convert->format == GL_RGBA &&                              \
217
             convert->type == GL_UNSIGNED_BYTE )                        \
218
   {                                                                    \
219
      tab = name##_tab_abgr8888_to_argb8888;                            \
220
   }                                                                    \
221
   else if ( convert->format == GL_RGB &&                               \
222
             convert->type == GL_UNSIGNED_BYTE )                        \
223
   {                                                                    \
224
      tab = name##_tab_bgr888_to_argb8888;                              \
225
   }                                                                    \
226
   else                                                                 \
227
   {                                                                    \
228
      /* Can't handle this source format/type combination */            \
229
      return GL_FALSE;                                                  \
230
   }                                                                    \
231
                                                                        \
232
   return tab[index]( convert );                                        \
233
}
234
 
235
CONVERT_ARGB8888( texsubimage2d )
236
CONVERT_ARGB8888( texsubimage3d )
237
 
238
 
239
 
240
/* =============================================================
241
 * Convert to RGB888 textures:
242
 */
243
 
244
static GLboolean
245
convert_texsubimage2d_rgb888( const struct convert_info *convert )
246
{
247
   /* This is a placeholder for now...
248
    */
249
   return GL_FALSE;
250
}
251
 
252
static GLboolean
253
convert_texsubimage3d_rgb888( const struct convert_info *convert )
254
{
255
   /* This is a placeholder for now...
256
    */
257
   return GL_FALSE;
258
}
259
 
260
 
261
 
262
/* =============================================================
263
 * Convert to RGB565 textures:
264
 */
265
 
266
#define DST_TYPE                GLushort
267
#define DST_TEXELS_PER_DWORD    2
268
 
269
#define CONVERT_TEXEL( dst, src )                                       \
270
        dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
271
 
272
#define CONVERT_DIRECT
273
 
274
#define SRC_TEXEL_BYTES         2
275
 
276
#define TAG(x) x##_rgb565_direct
277
#define PRESERVE_DST_TYPE
278
#include "texutil_tmp.h"
279
 
280
 
281
#define CONVERT_TEXEL( dst, src )                                       \
282
        dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
283
 
284
#define CONVERT_TEXEL_DWORD( dst, src )                                 \
285
        dst = APPEND16( PACK_COLOR_565_LE( src[0], src[1], src[2] ),    \
286
                        PACK_COLOR_565_LE( src[3], src[4], src[5] ) )
287
 
288
#define SRC_TEXEL_BYTES         3
289
 
290
#define TAG(x) x##_bgr888_to_rgb565
291
#define PRESERVE_DST_TYPE
292
#include "texutil_tmp.h"
293
 
294
 
295
#define CONVERT_TEXEL( dst, src )                                       \
296
        dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
297
 
298
#define CONVERT_TEXEL_DWORD( dst, src )                                 \
299
        dst = APPEND16( PACK_COLOR_565_LE( src[0], src[1], src[2] ),    \
300
                        PACK_COLOR_565_LE( src[4], src[5], src[6] ) )
301
 
302
#define SRC_TEXEL_BYTES         4
303
 
304
#define TAG(x) x##_abgr8888_to_rgb565
305
#include "texutil_tmp.h"
306
 
307
 
308
#define CONVERT_RGB565( name )                                          \
309
static GLboolean                                                        \
310
convert_##name##_rgb565( const struct convert_info *convert )           \
311
{                                                                       \
312
   convert_func *tab;                                                   \
313
   GLint index = convert->index;                                        \
314
                                                                        \
315
   if ( convert->format == GL_RGB &&                                    \
316
        convert->type == GL_UNSIGNED_SHORT_5_6_5 )                      \
317
   {                                                                    \
318
      tab = name##_tab_rgb565_direct;                                   \
319
   }                                                                    \
320
   else if ( convert->format == GL_RGB &&                               \
321
             convert->type == GL_UNSIGNED_BYTE )                        \
322
   {                                                                    \
323
      tab = name##_tab_bgr888_to_rgb565;                                \
324
   }                                                                    \
325
   else if ( convert->format == GL_RGBA &&                              \
326
             convert->type == GL_UNSIGNED_BYTE )                        \
327
   {                                                                    \
328
      tab = name##_tab_abgr8888_to_rgb565;                              \
329
   }                                                                    \
330
   else                                                                 \
331
   {                                                                    \
332
      /* Can't handle this source format/type combination */            \
333
      return GL_FALSE;                                                  \
334
   }                                                                    \
335
                                                                        \
336
   return tab[index]( convert );                                        \
337
}
338
 
339
CONVERT_RGB565( texsubimage2d )
340
CONVERT_RGB565( texsubimage3d )
341
 
342
 
343
 
344
/* =============================================================
345
 * Convert to ARGB4444 textures:
346
 */
347
 
348
#define DST_TYPE                GLushort
349
#define DST_TEXELS_PER_DWORD    2
350
 
351
#define CONVERT_TEXEL( dst, src )                                       \
352
        dst = PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] )
353
 
354
#define CONVERT_DIRECT
355
 
356
#define SRC_TEXEL_BYTES         2
357
 
358
#define TAG(x) x##_argb4444_direct
359
#define PRESERVE_DST_TYPE
360
#include "texutil_tmp.h"
361
 
362
 
363
#define CONVERT_TEXEL( dst, src )                                       \
364
        dst = PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] )
365
 
366
#define CONVERT_TEXEL_DWORD( dst, src )                                 \
367
        dst = APPEND16( PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] ),   \
368
                        PACK_COLOR_4444_LE( src[7], src[4], src[5], src[6] ) )
369
 
370
#define SRC_TEXEL_BYTES         4
371
 
372
#define TAG(x) x##_abgr8888_to_argb4444
373
#include "texutil_tmp.h"
374
 
375
 
376
#define CONVERT_ARGB4444( name )                                        \
377
static GLboolean                                                        \
378
convert_##name##_argb4444( const struct convert_info *convert )         \
379
{                                                                       \
380
   convert_func *tab;                                                   \
381
   GLint index = convert->index;                                        \
382
                                                                        \
383
   if ( convert->format == GL_BGRA &&                                   \
384
        convert->type == GL_UNSIGNED_SHORT_4_4_4_4_REV )                \
385
   {                                                                    \
386
      tab = name##_tab_argb4444_direct;                                 \
387
   }                                                                    \
388
   else if ( convert->format == GL_RGBA &&                              \
389
             convert->type == GL_UNSIGNED_BYTE )                        \
390
   {                                                                    \
391
      tab = name##_tab_abgr8888_to_argb4444;                            \
392
   }                                                                    \
393
   else                                                                 \
394
   {                                                                    \
395
      /* Can't handle this source format/type combination */            \
396
      return GL_FALSE;                                                  \
397
   }                                                                    \
398
                                                                        \
399
   return tab[index]( convert );                                        \
400
}
401
 
402
CONVERT_ARGB4444( texsubimage2d )
403
CONVERT_ARGB4444( texsubimage3d )
404
 
405
 
406
 
407
/* =============================================================
408
 * Convert to ARGB1555 textures:
409
 */
410
 
411
#define DST_TYPE                GLushort
412
#define DST_TEXELS_PER_DWORD    2
413
 
414
#define CONVERT_TEXEL( dst, src )                                       \
415
        dst = PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] )
416
 
417
#define CONVERT_DIRECT
418
 
419
#define SRC_TEXEL_BYTES         2
420
 
421
#define TAG(x) x##_argb1555_direct
422
#define PRESERVE_DST_TYPE
423
#include "texutil_tmp.h"
424
 
425
 
426
#ifdef MESA_BIG_ENDIAN
427
 
428
#define CONVERT_TEXEL( dst, src )                                       \
429
        { const GLushort s = *(GLushort *)src;                          \
430
          dst = (s >> 9) | ((s & 0x1ff) << 7); }
431
 
432
#define CONVERT_TEXEL_DWORD( dst, src )                                 \
433
        { const GLuint s = ((fi_type *)src)->i;                         \
434
          dst = (((s & 0xfe00fe00) >> 9) |                              \
435
                 ((s & 0x01ff01ff) << 7)); }
436
 
437
#else
438
 
439
#define CONVERT_TEXEL( dst, src )                                       \
440
        { const GLushort s = *(GLushort *)src;                          \
441
          dst = (s >> 1) | ((s & 1) << 15); }
442
 
443
#define CONVERT_TEXEL_DWORD( dst, src )                                 \
444
        { const GLuint s = ((fi_type *)src)->i;                         \
445
          dst = (((s & 0xfffefffe) >> 1) |                              \
446
                 ((s & 0x00010001) << 15)); }
447
 
448
#endif
449
 
450
#define SRC_TEXEL_BYTES         2
451
 
452
#define TAG(x) x##_rgba5551_to_argb1555
453
#define PRESERVE_DST_TYPE
454
#include "texutil_tmp.h"
455
 
456
 
457
#define CONVERT_TEXEL( dst, src )                                       \
458
        dst = PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] )
459
 
460
#define CONVERT_TEXEL_DWORD( dst, src )                                 \
461
        dst = APPEND16( PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] ),   \
462
                        PACK_COLOR_1555_LE( src[7], src[4], src[5], src[6] ) )
463
 
464
#define SRC_TEXEL_BYTES         4
465
 
466
#define TAG(x) x##_abgr8888_to_argb1555
467
#include "texutil_tmp.h"
468
 
469
 
470
#define CONVERT_ARGB1555( name )                                        \
471
static GLboolean                                                        \
472
convert_##name##_argb1555( const struct convert_info *convert )         \
473
{                                                                       \
474
   convert_func *tab;                                                   \
475
   GLint index = convert->index;                                        \
476
                                                                        \
477
   if ( convert->format == GL_BGRA &&                                   \
478
        convert->type == GL_UNSIGNED_SHORT_1_5_5_5_REV )                \
479
   {                                                                    \
480
      tab = name##_tab_argb1555_direct;                                 \
481
   }                                                                    \
482
   else if ( convert->format == GL_RGBA &&                              \
483
             convert->type == GL_UNSIGNED_SHORT_5_5_5_1 )               \
484
   {                                                                    \
485
      tab = name##_tab_rgba5551_to_argb1555;                            \
486
   }                                                                    \
487
   else if ( convert->format == GL_RGBA &&                              \
488
             convert->type == GL_UNSIGNED_BYTE )                        \
489
   {                                                                    \
490
      tab = name##_tab_abgr8888_to_argb1555;                            \
491
   }                                                                    \
492
   else                                                                 \
493
   {                                                                    \
494
      /* Can't handle this source format/type combination */            \
495
      return GL_FALSE;                                                  \
496
   }                                                                    \
497
                                                                        \
498
   return tab[index]( convert );                                        \
499
}
500
 
501
CONVERT_ARGB1555( texsubimage2d )
502
CONVERT_ARGB1555( texsubimage3d )
503
 
504
 
505
 
506
/* =============================================================
507
 * AL88 textures:
508
 */
509
 
510
#define DST_TYPE                GLushort
511
#define DST_TEXELS_PER_DWORD    2
512
 
513
#define CONVERT_TEXEL( dst, src )                                       \
514
        dst = PACK_COLOR_88_LE( src[0], src[1] )
515
 
516
#define CONVERT_DIRECT
517
 
518
#define SRC_TEXEL_BYTES         2
519
 
520
#define TAG(x) x##_al88_direct
521
#define PRESERVE_DST_TYPE
522
#include "texutil_tmp.h"
523
 
524
 
525
#define CONVERT_TEXEL( dst, src )                                       \
526
        dst = PACK_COLOR_88_LE( src[0], 0x00 )
527
 
528
#define CONVERT_TEXEL_DWORD( dst, src )                                 \
529
        dst = APPEND16( PACK_COLOR_88_LE( src[0], 0x00 ),                       \
530
                        PACK_COLOR_88_LE( src[1], 0x00 ) )
531
 
532
#define SRC_TEXEL_BYTES         1
533
 
534
#define TAG(x) x##_a8_to_al88
535
#define PRESERVE_DST_TYPE
536
#include "texutil_tmp.h"
537
 
538
 
539
#define CONVERT_TEXEL( dst, src )                                       \
540
        dst = PACK_COLOR_88_LE( 0xff, src[0] )
541
 
542
#define CONVERT_TEXEL_DWORD( dst, src )                                 \
543
        dst = APPEND16( PACK_COLOR_88_LE( 0xff, src[0] ),                       \
544
                        PACK_COLOR_88_LE( 0xff, src[1] ) )
545
 
546
#define SRC_TEXEL_BYTES         1
547
 
548
#define TAG(x) x##_l8_to_al88
549
#define PRESERVE_DST_TYPE
550
#include "texutil_tmp.h"
551
 
552
 
553
#define CONVERT_TEXEL( dst, src )                                       \
554
        dst = PACK_COLOR_88_LE( src[3], src[0] )
555
 
556
#define CONVERT_TEXEL_DWORD( dst, src )                                 \
557
        dst = APPEND16( PACK_COLOR_88_LE( src[3], src[0] ),             \
558
                        PACK_COLOR_88_LE( src[7], src[4] ) )
559
 
560
#define SRC_TEXEL_BYTES         4
561
 
562
#define TAG(x) x##_abgr8888_to_al88
563
#include "texutil_tmp.h"
564
 
565
 
566
#define CONVERT_AL88( name )                                            \
567
static GLboolean                                                        \
568
convert_##name##_al88( const struct convert_info *convert )             \
569
{                                                                       \
570
   convert_func *tab;                                                   \
571
   GLint index = convert->index;                                        \
572
                                                                        \
573
   if ( convert->format == GL_LUMINANCE_ALPHA &&                        \
574
        convert->type == GL_UNSIGNED_BYTE )                             \
575
   {                                                                    \
576
      tab = name##_tab_al88_direct;                                     \
577
   }                                                                    \
578
   else if ( convert->format == GL_ALPHA &&                             \
579
             convert->type == GL_UNSIGNED_BYTE )                        \
580
   {                                                                    \
581
      tab = name##_tab_a8_to_al88;                                      \
582
   }                                                                    \
583
   else if ( convert->format == GL_LUMINANCE &&                         \
584
             convert->type == GL_UNSIGNED_BYTE )                        \
585
   {                                                                    \
586
      tab = name##_tab_l8_to_al88;                                      \
587
   }                                                                    \
588
   else if ( convert->format == GL_RGBA &&                              \
589
             convert->type == GL_UNSIGNED_BYTE )                        \
590
   {                                                                    \
591
      tab = name##_tab_abgr8888_to_al88;                                \
592
   }                                                                    \
593
   else                                                                 \
594
   {                                                                    \
595
      /* Can't handle this source format/type combination */            \
596
      return GL_FALSE;                                                  \
597
   }                                                                    \
598
                                                                        \
599
   return tab[index]( convert );                                        \
600
}
601
 
602
CONVERT_AL88( texsubimage2d )
603
CONVERT_AL88( texsubimage3d )
604
 
605
 
606
 
607
/* =============================================================
608
 * Convert to RGB332 textures:
609
 */
610
 
611
static GLboolean
612
convert_texsubimage2d_rgb332( const struct convert_info *convert )
613
{
614
   /* This is a placeholder for now...
615
    */
616
   return GL_FALSE;
617
}
618
 
619
static GLboolean
620
convert_texsubimage3d_rgb332( const struct convert_info *convert )
621
{
622
   /* This is a placeholder for now...
623
    */
624
   return GL_FALSE;
625
}
626
 
627
 
628
 
629
/* =============================================================
630
 * CI8 (and all other single-byte texel) textures:
631
 */
632
 
633
#define DST_TYPE                GLubyte
634
#define DST_TEXELS_PER_DWORD    4
635
 
636
#define CONVERT_TEXEL( dst, src )       dst = src[0]
637
 
638
#define CONVERT_DIRECT
639
 
640
#define SRC_TEXEL_BYTES         1
641
 
642
#define TAG(x) x##_ci8_direct
643
#include "texutil_tmp.h"
644
 
645
 
646
#define CONVERT_CI8( name )                                             \
647
static GLboolean                                                        \
648
convert_##name##_ci8( const struct convert_info *convert )              \
649
{                                                                       \
650
   convert_func *tab;                                                   \
651
   GLint index = convert->index;                                        \
652
                                                                        \
653
   if ( ( convert->format == GL_ALPHA ||                                \
654
          convert->format == GL_LUMINANCE ||                            \
655
          convert->format == GL_INTENSITY ||                            \
656
          convert->format == GL_COLOR_INDEX ) &&                        \
657
        convert->type == GL_UNSIGNED_BYTE )                             \
658
   {                                                                    \
659
      tab = name##_tab_ci8_direct;                                      \
660
   }                                                                    \
661
   else                                                                 \
662
   {                                                                    \
663
      /* Can't handle this source format/type combination */            \
664
      return GL_FALSE;                                                  \
665
   }                                                                    \
666
                                                                        \
667
   return tab[index]( convert );                                        \
668
}
669
 
670
CONVERT_CI8( texsubimage2d )
671
CONVERT_CI8( texsubimage3d )
672
 
673
 
674
/* =============================================================
675
 * convert to YCBCR textures:
676
 */
677
 
678
#define DST_TYPE                GLushort
679
#define DST_TEXELS_PER_DWORD    2
680
 
681
#define CONVERT_TEXEL( dst, src ) \
682
   dst = (src[0] << 8) | src[1];
683
 
684
#define CONVERT_DIRECT
685
 
686
#define SRC_TEXEL_BYTES         2
687
 
688
#define TAG(x) x##_ycbcr_direct
689
#include "texutil_tmp.h"
690
 
691
 
692
#define CONVERT_YCBCR( name )                                           \
693
static GLboolean                                                        \
694
convert_##name##_ycbcr( const struct convert_info *convert )            \
695
{                                                                       \
696
   convert_func *tab;                                                   \
697
   GLint index = convert->index;                                        \
698
                                                                        \
699
   if (convert->format != GL_YCBCR_MESA) {                              \
700
      /* Can't handle this source format/type combination */            \
701
      return GL_FALSE;                                                  \
702
   }                                                                    \
703
   tab = name##_tab_ycbcr_direct;                                       \
704
                                                                        \
705
   return tab[index]( convert );                                        \
706
}
707
 
708
CONVERT_YCBCR( texsubimage2d )
709
CONVERT_YCBCR( texsubimage3d )
710
 
711
 
712
/* =============================================================
713
 * convert to YCBCR_REV textures:
714
 */
715
 
716
#define DST_TYPE                GLushort
717
#define DST_TEXELS_PER_DWORD    2
718
 
719
#define CONVERT_TEXEL( dst, src ) \
720
   dst = (src[1] << 8) | src[0];
721
 
722
#define CONVERT_DIRECT
723
 
724
#define SRC_TEXEL_BYTES         2
725
 
726
#define TAG(x) x##_ycbcr_rev_direct
727
#include "texutil_tmp.h"
728
 
729
 
730
#define CONVERT_YCBCR_REV( name )                                       \
731
static GLboolean                                                        \
732
convert_##name##_ycbcr_rev( const struct convert_info *convert )        \
733
{                                                                       \
734
   convert_func *tab;                                                   \
735
   GLint index = convert->index;                                        \
736
                                                                        \
737
   if (convert->format != GL_YCBCR_MESA) {                              \
738
      /* Can't handle this source format/type combination */            \
739
      return GL_FALSE;                                                  \
740
   }                                                                    \
741
   tab = name##_tab_ycbcr_rev_direct;                                   \
742
                                                                        \
743
   return tab[index]( convert );                                        \
744
}
745
 
746
CONVERT_YCBCR_REV( texsubimage2d )
747
CONVERT_YCBCR_REV( texsubimage3d )
748
 
749
 
750
 
751
/* =============================================================
752
 * Global entry points
753
 */
754
 
755
static convert_func convert_texsubimage2d_tab[] = {
756
   convert_texsubimage2d_rgba8888,
757
   convert_texsubimage2d_argb8888,
758
   convert_texsubimage2d_rgb888,
759
   convert_texsubimage2d_rgb565,
760
   convert_texsubimage2d_argb4444,
761
   convert_texsubimage2d_argb1555,
762
   convert_texsubimage2d_al88,
763
   convert_texsubimage2d_rgb332,
764
   convert_texsubimage2d_ci8,           /* These are all the same... */
765
   convert_texsubimage2d_ci8,
766
   convert_texsubimage2d_ci8,
767
   convert_texsubimage2d_ci8,
768
   convert_texsubimage2d_ycbcr,
769
   convert_texsubimage2d_ycbcr_rev,
770
};
771
 
772
static convert_func convert_texsubimage3d_tab[] = {
773
   convert_texsubimage3d_rgba8888,
774
   convert_texsubimage3d_argb8888,
775
   convert_texsubimage3d_rgb888,
776
   convert_texsubimage3d_rgb565,
777
   convert_texsubimage3d_argb4444,
778
   convert_texsubimage3d_argb1555,
779
   convert_texsubimage3d_al88,
780
   convert_texsubimage3d_rgb332,
781
   convert_texsubimage3d_ci8,           /* These are all the same... */
782
   convert_texsubimage3d_ci8,
783
   convert_texsubimage3d_ci8,
784
   convert_texsubimage3d_ci8,
785
   convert_texsubimage3d_ycbcr,
786
   convert_texsubimage3d_ycbcr_rev,
787
};
788
 
789
 
790
/* See if we need to care about the pixel store attributes when we're
791
 * converting the texture image.  This should be stored as
792
 * unpacking->_SomeBoolean and updated when the values change, to avoid
793
 * testing every time...
794
 */
795
static INLINE GLboolean
796
convert_needs_unpacking( const struct gl_pixelstore_attrib *unpacking,
797
                       GLenum format, GLenum type )
798
{
799
   if ( ( unpacking->Alignment == 1 ||
800
          ( unpacking->Alignment == 4 &&   /* Pick up the common Q3A case... */
801
            format == GL_RGBA && type == GL_UNSIGNED_BYTE ) ) &&
802
        unpacking->RowLength == 0 &&
803
        unpacking->SkipPixels == 0 &&
804
        unpacking->SkipRows == 0 &&
805
        unpacking->ImageHeight == 0 &&
806
        unpacking->SkipImages == 0 &&
807
        unpacking->SwapBytes == GL_FALSE &&
808
        unpacking->LsbFirst == GL_FALSE ) {
809
      return GL_FALSE;
810
   } else {
811
      return GL_TRUE;
812
   }
813
}
814
 
815
 
816
GLboolean
817
_mesa_convert_texsubimage1d( GLint mesaFormat,
818
                             GLint xoffset,
819
                             GLint width,
820
                             GLenum format, GLenum type,
821
                             const struct gl_pixelstore_attrib *unpacking,
822
                             const GLvoid *srcImage, GLvoid *dstImage )
823
{
824
   struct convert_info convert;
825
 
826
   ASSERT( unpacking );
827
   ASSERT( srcImage );
828
   ASSERT( dstImage );
829
 
830
   ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
831
   ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
832
 
833
   /* Make it easier to pass all the parameters around.
834
    */
835
   convert.xoffset = xoffset;
836
   convert.yoffset = 0;
837
   convert.width = width;
838
   convert.height = 1;
839
   convert.format = format;
840
   convert.type = type;
841
   convert.unpacking = unpacking;
842
   convert.srcImage = srcImage;
843
   convert.dstImage = dstImage;
844
 
845
   convert.index = 0;
846
 
847
   if ( convert_needs_unpacking( unpacking, format, type ) )
848
      convert.index |= CONVERT_UNPACKING_BIT;
849
 
850
   ASSERT(convert.index < 4);
851
 
852
   return convert_texsubimage2d_tab[mesaFormat]( &convert );
853
}
854
 
855
 
856
/* Convert a user's 2D image into a texture image.  This basically
857
 * repacks pixel data into the special texture formats used by core Mesa
858
 * and the DRI drivers.  This function can do full images or subimages.
859
 *
860
 * We return a boolean because this function may not accept some kinds
861
 * of source image formats and/or types.  For example, if the incoming
862
 * format/type = GL_BGR, GL_UNSIGNED_INT this function probably won't
863
 * be able to do the conversion.
864
 *
865
 * In that case, the incoming image should first be simplified to one of
866
 * the "canonical" formats (GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA,
867
 * GL_INTENSITY, GL_RGB, GL_RGBA) and types (GL_CHAN).  We can do that
868
 * with the _mesa_transfer_teximage() function.  That function will also
869
 * do image transfer operations such as scale/bias and convolution.
870
 *
871
 * Input:
872
 *   mesaFormat - one of the MESA_FORMAT_* values from texformat.h
873
 *   xoffset, yoffset - position in dest image to put data
874
 *   width, height - incoming image size, also size of dest region.
875
 *   dstImageWidth - width (row stride) of dest image in pixels
876
 *   format, type - incoming image format and type
877
 *   unpacking - describes incoming image unpacking
878
 *   srcImage - pointer to source image
879
 *   destImage - pointer to dest image
880
 */
881
GLboolean
882
_mesa_convert_texsubimage2d( GLint mesaFormat,  /* dest */
883
                             GLint xoffset, GLint yoffset,
884
                             GLint width, GLint height,
885
                             GLint destImageWidth,
886
                             GLenum format, GLenum type,  /* source */
887
                             const struct gl_pixelstore_attrib *unpacking,
888
                             const GLvoid *srcImage, GLvoid *dstImage )
889
{
890
   struct convert_info convert;
891
 
892
   ASSERT( unpacking );
893
   ASSERT( srcImage );
894
   ASSERT( dstImage );
895
 
896
   ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
897
   ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
898
 
899
   /* Make it easier to pass all the parameters around.
900
    */
901
   convert.xoffset = xoffset;
902
   convert.yoffset = yoffset;
903
   convert.width = width;
904
   convert.height = height;
905
   convert.dstImageWidth = destImageWidth;
906
   convert.format = format;
907
   convert.type = type;
908
   convert.unpacking = unpacking;
909
   convert.srcImage = srcImage;
910
   convert.dstImage = dstImage;
911
 
912
   convert.index = 0;
913
 
914
   if ( convert_needs_unpacking( unpacking, format, type ) )
915
      convert.index |= CONVERT_UNPACKING_BIT;
916
 
917
   if ( width != destImageWidth )
918
      convert.index |= CONVERT_STRIDE_BIT;
919
 
920
   return convert_texsubimage2d_tab[mesaFormat]( &convert );
921
}
922
 
923
GLboolean
924
_mesa_convert_texsubimage3d( GLint mesaFormat,  /* dest */
925
                             GLint xoffset, GLint yoffset, GLint zoffset,
926
                             GLint width, GLint height, GLint depth,
927
                             GLint dstImageWidth, GLint dstImageHeight,
928
                             GLenum format, GLenum type,  /* source */
929
                             const struct gl_pixelstore_attrib *unpacking,
930
                             const GLvoid *srcImage, GLvoid *dstImage )
931
{
932
   struct convert_info convert;
933
 
934
   ASSERT( unpacking );
935
   ASSERT( srcImage );
936
   ASSERT( dstImage );
937
 
938
   ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
939
   ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
940
 
941
   /* Make it easier to pass all the parameters around.
942
    */
943
   convert.xoffset = xoffset;
944
   convert.yoffset = yoffset;
945
   convert.zoffset = zoffset;
946
   convert.width = width;
947
   convert.height = height;
948
   convert.depth = depth;
949
   convert.dstImageWidth = dstImageWidth;
950
   convert.dstImageHeight = dstImageHeight;
951
   convert.format = format;
952
   convert.type = type;
953
   convert.unpacking = unpacking;
954
   convert.srcImage = srcImage;
955
   convert.dstImage = dstImage;
956
 
957
   convert.index = 0;
958
 
959
   if ( convert_needs_unpacking( unpacking, format, type ) )
960
      convert.index |= CONVERT_UNPACKING_BIT;
961
 
962
   if ( width != dstImageWidth || height != dstImageHeight )
963
      convert.index |= CONVERT_STRIDE_BIT;
964
 
965
   return convert_texsubimage3d_tab[mesaFormat]( &convert );
966
}
967
 
968
 
969
 
970
/* Nearest filtering only (for broken hardware that can't support
971
 * all aspect ratios).  This can be made a lot faster, but I don't
972
 * really care enough...
973
 */
974
void _mesa_rescale_teximage2d( GLuint bytesPerPixel, GLuint dstRowStride,
975
                               GLint srcWidth, GLint srcHeight,
976
                               GLint dstWidth, GLint dstHeight,
977
                               const GLvoid *srcImage, GLvoid *dstImage )
978
{
979
   GLint row, col;
980
 
981
#define INNER_LOOP( TYPE, HOP, WOP )                                    \
982
   for ( row = 0 ; row < dstHeight ; row++ ) {                          \
983
      GLint srcRow = row HOP hScale;                                    \
984
      for ( col = 0 ; col < dstWidth ; col++ ) {                        \
985
         GLint srcCol = col WOP wScale;                                 \
986
         dst[col] = src[srcRow * srcWidth + srcCol];                    \
987
      }                                                                 \
988
      dst = (TYPE *) ((GLubyte *) dst + dstRowStride);                  \
989
   }                                                                    \
990
 
991
#define RESCALE_IMAGE( TYPE )                                           \
992
do {                                                                    \
993
   const TYPE *src = (const TYPE *)srcImage;                            \
994
   TYPE *dst = (TYPE *)dstImage;                                        \
995
                                                                        \
996
   if ( srcHeight <= dstHeight ) {                                      \
997
      const GLint hScale = dstHeight / srcHeight;                       \
998
      if ( srcWidth <= dstWidth ) {                                     \
999
         const GLint wScale = dstWidth / srcWidth;                      \
1000
         INNER_LOOP( TYPE, /, / );                                      \
1001
      }                                                                 \
1002
      else {                                                            \
1003
         const GLint wScale = srcWidth / dstWidth;                      \
1004
         INNER_LOOP( TYPE, /, * );                                      \
1005
      }                                                                 \
1006
   }                                                                    \
1007
   else {                                                               \
1008
      const GLint hScale = srcHeight / dstHeight;                       \
1009
      if ( srcWidth <= dstWidth ) {                                     \
1010
         const GLint wScale = dstWidth / srcWidth;                      \
1011
         INNER_LOOP( TYPE, *, / );                                      \
1012
      }                                                                 \
1013
      else {                                                            \
1014
         const GLint wScale = srcWidth / dstWidth;                      \
1015
         INNER_LOOP( TYPE, *, * );                                      \
1016
      }                                                                 \
1017
   }                                                                    \
1018
} while (0)
1019
 
1020
   switch ( bytesPerPixel ) {
1021
   case 4:
1022
      RESCALE_IMAGE( GLuint );
1023
      break;
1024
 
1025
   case 2:
1026
      RESCALE_IMAGE( GLushort );
1027
      break;
1028
 
1029
   case 1:
1030
      RESCALE_IMAGE( GLubyte );
1031
      break;
1032
   default:
1033
      _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
1034
   }
1035
}