Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
 * Mesa 3-D graphics library
3
 * Version:  6.5
4
 *
5
 * Copyright (C) 1999-2006  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
#include "glheader.h"
26
#include "imports.h"
27
#include "context.h"
28
#include "formats.h"
29
#include "mtypes.h"
30
#include "depthstencil.h"
31
#include "renderbuffer.h"
32
 
33
 
34
/**
35
 * Adaptor/wrappers for GL_DEPTH_STENCIL renderbuffers.
36
 *
37
 * The problem with a GL_DEPTH_STENCIL renderbuffer is that sometimes we
38
 * want to treat it as a stencil buffer, other times we want to treat it
39
 * as a depth/z buffer and still other times when we want to treat it as
40
 * a combined Z+stencil buffer!  That implies we need three different sets
41
 * of Get/Put functions.
42
 *
43
 * We solve this by wrapping the Z24_S8 or S8_Z24 renderbuffer with depth and
44
 * stencil adaptors, each with the right kind of depth/stencil Get/Put functions.
45
 */
46
 
47
 
48
static void *
49
nop_get_pointer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
50
{
51
   (void) ctx;
52
   (void) rb;
53
   (void) x;
54
   (void) y;
55
   return NULL;
56
}
57
 
58
 
59
/**
60
 * Delete a depth or stencil wrapper renderbuffer.
61
 */
62
static void
63
delete_wrapper(struct gl_renderbuffer *rb)
64
{
65
   ASSERT(rb->Format == MESA_FORMAT_S8 ||
66
          rb->Format == MESA_FORMAT_X8_Z24);
67
   _mesa_reference_renderbuffer(&rb->Wrapped, NULL);
68
   free(rb);
69
}
70
 
71
 
72
/**
73
 * Realloc storage for wrapper.
74
 */
75
static GLboolean
76
alloc_wrapper_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
77
                      GLenum internalFormat, GLuint width, GLuint height)
78
{
79
   /* just pass this on to the wrapped renderbuffer */
80
   struct gl_renderbuffer *dsrb = rb->Wrapped;
81
   GLboolean retVal;
82
 
83
   (void) internalFormat;
84
 
85
   ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
86
          dsrb->Format == MESA_FORMAT_Z24_X8 ||
87
          dsrb->Format == MESA_FORMAT_S8_Z24 ||
88
          dsrb->Format == MESA_FORMAT_X8_Z24);
89
 
90
   retVal = dsrb->AllocStorage(ctx, dsrb, dsrb->InternalFormat, width, height);
91
   if (retVal) {
92
      rb->Width = width;
93
      rb->Height = height;
94
   }
95
   return retVal;
96
}
97
 
98
 
99
 
100
 
101
/*======================================================================
102
 * Depth wrapper around depth/stencil renderbuffer
103
 */
104
 
105
static void
106
get_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
107
            GLint x, GLint y, void *values)
108
{
109
   struct gl_renderbuffer *dsrb = z24rb->Wrapped;
110
   GLuint temp[MAX_WIDTH], i;
111
   GLuint *dst = (GLuint *) values;
112
   const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
113
   ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
114
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
115
   if (!src) {
116
      dsrb->GetRow(ctx, dsrb, count, x, y, temp);
117
      src = temp;
118
   }
119
   if (dsrb->Format == MESA_FORMAT_Z24_S8) {
120
      for (i = 0; i < count; i++) {
121
         dst[i] = src[i] >> 8;
122
      }
123
   }
124
   else {
125
      assert(dsrb->Format == MESA_FORMAT_S8_Z24);
126
      for (i = 0; i < count; i++) {
127
         dst[i] = src[i] & 0xffffff;
128
      }
129
   }
130
}
131
 
132
static void
133
get_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
134
               const GLint x[], const GLint y[], void *values)
135
{
136
   struct gl_renderbuffer *dsrb = z24rb->Wrapped;
137
   GLuint temp[MAX_WIDTH], i;
138
   GLuint *dst = (GLuint *) values;
139
   ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
140
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
141
   ASSERT(count <= MAX_WIDTH);
142
   /* don't bother trying direct access */
143
   dsrb->GetValues(ctx, dsrb, count, x, y, temp);
144
   if (dsrb->Format == MESA_FORMAT_Z24_S8) {
145
      for (i = 0; i < count; i++) {
146
         dst[i] = temp[i] >> 8;
147
      }
148
   }
149
   else {
150
      assert(dsrb->Format == MESA_FORMAT_S8_Z24);
151
      for (i = 0; i < count; i++) {
152
         dst[i] = temp[i] & 0xffffff;
153
      }
154
   }
155
}
156
 
157
static void
158
put_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
159
            GLint x, GLint y, const void *values, const GLubyte *mask)
160
{
161
   struct gl_renderbuffer *dsrb = z24rb->Wrapped;
162
   const GLuint *src = (const GLuint *) values;
163
   GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
164
   ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
165
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
166
   if (dst) {
167
      /* direct access */
168
      GLuint i;
169
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
170
         for (i = 0; i < count; i++) {
171
            if (!mask || mask[i]) {
172
               dst[i] = (src[i] << 8) | (dst[i] & 0xff);
173
            }
174
         }
175
      }
176
      else {
177
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
178
         for (i = 0; i < count; i++) {
179
            if (!mask || mask[i]) {
180
               dst[i] = (src[i] & 0xffffff) | (dst[i] & 0xff000000);
181
            }
182
         }
183
      }
184
   }
185
   else {
186
      /* get, modify, put */
187
      GLuint temp[MAX_WIDTH], i;
188
      dsrb->GetRow(ctx, dsrb, count, x, y, temp);
189
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
190
         for (i = 0; i < count; i++) {
191
            if (!mask || mask[i]) {
192
               temp[i] = (src[i] << 8) | (temp[i] & 0xff);
193
            }
194
         }
195
      }
196
      else {
197
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
198
         for (i = 0; i < count; i++) {
199
            if (!mask || mask[i]) {
200
               temp[i] = (src[i] & 0xffffff) | (temp[i] & 0xff000000);
201
            }
202
         }
203
      }
204
      dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
205
   }
206
}
207
 
208
static void
209
put_mono_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
210
                 GLint x, GLint y, const void *value, const GLubyte *mask)
211
{
212
   struct gl_renderbuffer *dsrb = z24rb->Wrapped;
213
   GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
214
   ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
215
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
216
   if (dst) {
217
      /* direct access */
218
      GLuint i;
219
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
220
         const GLuint shiftedVal = *((GLuint *) value) << 8;
221
         for (i = 0; i < count; i++) {
222
            if (!mask || mask[i]) {
223
               dst[i] = shiftedVal | (dst[i] & 0xff);
224
            }
225
         }
226
      }
227
      else {
228
         const GLuint shiftedVal = *((GLuint *) value);
229
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
230
         for (i = 0; i < count; i++) {
231
            if (!mask || mask[i]) {
232
               dst[i] = shiftedVal | (dst[i] & 0xff000000);
233
            }
234
         }
235
      }
236
   }
237
   else {
238
      /* get, modify, put */
239
      GLuint temp[MAX_WIDTH], i;
240
      dsrb->GetRow(ctx, dsrb, count, x, y, temp);
241
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
242
         const GLuint shiftedVal = *((GLuint *) value) << 8;
243
         for (i = 0; i < count; i++) {
244
            if (!mask || mask[i]) {
245
               temp[i] = shiftedVal | (temp[i] & 0xff);
246
            }
247
         }
248
      }
249
      else {
250
         const GLuint shiftedVal = *((GLuint *) value);
251
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
252
         for (i = 0; i < count; i++) {
253
            if (!mask || mask[i]) {
254
               temp[i] = shiftedVal | (temp[i] & 0xff000000);
255
            }
256
         }
257
      }
258
      dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
259
   }
260
}
261
 
262
static void
263
put_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
264
               const GLint x[], const GLint y[],
265
               const void *values, const GLubyte *mask)
266
{
267
   struct gl_renderbuffer *dsrb = z24rb->Wrapped;
268
   const GLuint *src = (const GLuint *) values;
269
   ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
270
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
271
   if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
272
      /* direct access */
273
      GLuint i;
274
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
275
         for (i = 0; i < count; i++) {
276
            if (!mask || mask[i]) {
277
               GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
278
               *dst = (src[i] << 8) | (*dst & 0xff);
279
            }
280
         }
281
      }
282
      else {
283
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
284
         for (i = 0; i < count; i++) {
285
            if (!mask || mask[i]) {
286
               GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
287
               *dst = (src[i] & 0xffffff) | (*dst & 0xff000000);
288
            }
289
         }
290
      }
291
   }
292
   else {
293
      /* get, modify, put */
294
      GLuint temp[MAX_WIDTH], i;
295
      dsrb->GetValues(ctx, dsrb, count, x, y, temp);
296
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
297
         for (i = 0; i < count; i++) {
298
            if (!mask || mask[i]) {
299
               temp[i] = (src[i] << 8) | (temp[i] & 0xff);
300
            }
301
         }
302
      }
303
      else {
304
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
305
         for (i = 0; i < count; i++) {
306
            if (!mask || mask[i]) {
307
               temp[i] = (src[i] & 0xffffff) | (temp[i] & 0xff000000);
308
            }
309
         }
310
      }
311
      dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
312
   }
313
}
314
 
315
static void
316
put_mono_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb,
317
                    GLuint count, const GLint x[], const GLint y[],
318
                    const void *value, const GLubyte *mask)
319
{
320
   struct gl_renderbuffer *dsrb = z24rb->Wrapped;
321
   GLuint temp[MAX_WIDTH], i;
322
   /* get, modify, put */
323
   dsrb->GetValues(ctx, dsrb, count, x, y, temp);
324
   if (dsrb->Format == MESA_FORMAT_Z24_S8) {
325
      const GLuint shiftedVal = *((GLuint *) value) << 8;
326
      for (i = 0; i < count; i++) {
327
         if (!mask || mask[i]) {
328
            temp[i] = shiftedVal | (temp[i] & 0xff);
329
         }
330
      }
331
   }
332
   else {
333
      const GLuint shiftedVal = *((GLuint *) value);
334
      assert(dsrb->Format == MESA_FORMAT_S8_Z24);
335
      for (i = 0; i < count; i++) {
336
         if (!mask || mask[i]) {
337
            temp[i] = shiftedVal | (temp[i] & 0xff000000);
338
         }
339
      }
340
   }
341
   dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
342
}
343
 
344
 
345
/**
346
 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
347
 * a depth renderbuffer.
348
 * \return new depth renderbuffer
349
 */
350
struct gl_renderbuffer *
351
_mesa_new_z24_renderbuffer_wrapper(struct gl_context *ctx,
352
                                   struct gl_renderbuffer *dsrb)
353
{
354
   struct gl_renderbuffer *z24rb;
355
 
356
   ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
357
          dsrb->Format == MESA_FORMAT_Z24_X8 ||
358
          dsrb->Format == MESA_FORMAT_S8_Z24 ||
359
          dsrb->Format == MESA_FORMAT_X8_Z24);
360
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
361
 
362
   z24rb = ctx->Driver.NewRenderbuffer(ctx, 0);
363
   if (!z24rb)
364
      return NULL;
365
 
366
   /* NOTE: need to do manual refcounting here */
367
   z24rb->Wrapped = dsrb;
368
   dsrb->RefCount++;
369
 
370
   z24rb->Name = dsrb->Name;
371
   z24rb->RefCount = 0;
372
   z24rb->Width = dsrb->Width;
373
   z24rb->Height = dsrb->Height;
374
   z24rb->InternalFormat = GL_DEPTH_COMPONENT24;
375
   z24rb->Format = MESA_FORMAT_X8_Z24;
376
   z24rb->_BaseFormat = GL_DEPTH_COMPONENT;
377
   z24rb->DataType = GL_UNSIGNED_INT;
378
   z24rb->Data = NULL;
379
   z24rb->Delete = delete_wrapper;
380
   z24rb->AllocStorage = alloc_wrapper_storage;
381
   z24rb->GetPointer = nop_get_pointer;
382
   z24rb->GetRow = get_row_z24;
383
   z24rb->GetValues = get_values_z24;
384
   z24rb->PutRow = put_row_z24;
385
   z24rb->PutRowRGB = NULL;
386
   z24rb->PutMonoRow = put_mono_row_z24;
387
   z24rb->PutValues = put_values_z24;
388
   z24rb->PutMonoValues = put_mono_values_z24;
389
 
390
   return z24rb;
391
}
392
 
393
 
394
/*======================================================================
395
 * Stencil wrapper around depth/stencil renderbuffer
396
 */
397
 
398
static void
399
get_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
400
           GLint x, GLint y, void *values)
401
{
402
   struct gl_renderbuffer *dsrb = s8rb->Wrapped;
403
   GLuint temp[MAX_WIDTH], i;
404
   GLubyte *dst = (GLubyte *) values;
405
   const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
406
   ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
407
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
408
   if (!src) {
409
      dsrb->GetRow(ctx, dsrb, count, x, y, temp);
410
      src = temp;
411
   }
412
   if (dsrb->Format == MESA_FORMAT_Z24_S8) {
413
      for (i = 0; i < count; i++) {
414
         dst[i] = src[i] & 0xff;
415
      }
416
   }
417
   else {
418
      assert(dsrb->Format == MESA_FORMAT_S8_Z24);
419
      for (i = 0; i < count; i++) {
420
         dst[i] = src[i] >> 24;
421
      }
422
   }
423
}
424
 
425
static void
426
get_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
427
              const GLint x[], const GLint y[], void *values)
428
{
429
   struct gl_renderbuffer *dsrb = s8rb->Wrapped;
430
   GLuint temp[MAX_WIDTH], i;
431
   GLubyte *dst = (GLubyte *) values;
432
   ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
433
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
434
   ASSERT(count <= MAX_WIDTH);
435
   /* don't bother trying direct access */
436
   dsrb->GetValues(ctx, dsrb, count, x, y, temp);
437
   if (dsrb->Format == MESA_FORMAT_Z24_S8) {
438
      for (i = 0; i < count; i++) {
439
         dst[i] = temp[i] & 0xff;
440
      }
441
   }
442
   else {
443
      assert(dsrb->Format == MESA_FORMAT_S8_Z24);
444
      for (i = 0; i < count; i++) {
445
         dst[i] = temp[i] >> 24;
446
      }
447
   }
448
}
449
 
450
static void
451
put_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
452
           GLint x, GLint y, const void *values, const GLubyte *mask)
453
{
454
   struct gl_renderbuffer *dsrb = s8rb->Wrapped;
455
   const GLubyte *src = (const GLubyte *) values;
456
   GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
457
   ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
458
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
459
   if (dst) {
460
      /* direct access */
461
      GLuint i;
462
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
463
         for (i = 0; i < count; i++) {
464
            if (!mask || mask[i]) {
465
               dst[i] = (dst[i] & 0xffffff00) | src[i];
466
            }
467
         }
468
      }
469
      else {
470
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
471
         for (i = 0; i < count; i++) {
472
            if (!mask || mask[i]) {
473
               dst[i] = (dst[i] & 0xffffff) | (src[i] << 24);
474
            }
475
         }
476
      }
477
   }
478
   else {
479
      /* get, modify, put */
480
      GLuint temp[MAX_WIDTH], i;
481
      dsrb->GetRow(ctx, dsrb, count, x, y, temp);
482
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
483
         for (i = 0; i < count; i++) {
484
            if (!mask || mask[i]) {
485
               temp[i] = (temp[i] & 0xffffff00) | src[i];
486
            }
487
         }
488
      }
489
      else {
490
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
491
         for (i = 0; i < count; i++) {
492
            if (!mask || mask[i]) {
493
               temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
494
            }
495
         }
496
      }
497
      dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
498
   }
499
}
500
 
501
static void
502
put_mono_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
503
                GLint x, GLint y, const void *value, const GLubyte *mask)
504
{
505
   struct gl_renderbuffer *dsrb = s8rb->Wrapped;
506
   const GLubyte val = *((GLubyte *) value);
507
   GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
508
   ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
509
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
510
   if (dst) {
511
      /* direct access */
512
      GLuint i;
513
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
514
         for (i = 0; i < count; i++) {
515
            if (!mask || mask[i]) {
516
               dst[i] = (dst[i] & 0xffffff00) | val;
517
            }
518
         }
519
      }
520
      else {
521
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
522
         for (i = 0; i < count; i++) {
523
            if (!mask || mask[i]) {
524
               dst[i] = (dst[i] & 0xffffff) | (val << 24);
525
            }
526
         }
527
      }
528
   }
529
   else {
530
      /* get, modify, put */
531
      GLuint temp[MAX_WIDTH], i;
532
      dsrb->GetRow(ctx, dsrb, count, x, y, temp);
533
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
534
         for (i = 0; i < count; i++) {
535
            if (!mask || mask[i]) {
536
               temp[i] = (temp[i] & 0xffffff00) | val;
537
            }
538
         }
539
      }
540
      else {
541
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
542
         for (i = 0; i < count; i++) {
543
            if (!mask || mask[i]) {
544
               temp[i] = (temp[i] & 0xffffff) | (val << 24);
545
            }
546
         }
547
      }
548
      dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
549
   }
550
}
551
 
552
static void
553
put_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
554
              const GLint x[], const GLint y[],
555
              const void *values, const GLubyte *mask)
556
{
557
   struct gl_renderbuffer *dsrb = s8rb->Wrapped;
558
   const GLubyte *src = (const GLubyte *) values;
559
   ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
560
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
561
   if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
562
      /* direct access */
563
      GLuint i;
564
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
565
         for (i = 0; i < count; i++) {
566
            if (!mask || mask[i]) {
567
               GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
568
               *dst = (*dst & 0xffffff00) | src[i];
569
            }
570
         }
571
      }
572
      else {
573
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
574
         for (i = 0; i < count; i++) {
575
            if (!mask || mask[i]) {
576
               GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
577
               *dst = (*dst & 0xffffff) | (src[i] << 24);
578
            }
579
         }
580
      }
581
   }
582
   else {
583
      /* get, modify, put */
584
      GLuint temp[MAX_WIDTH], i;
585
      dsrb->GetValues(ctx, dsrb, count, x, y, temp);
586
      if (dsrb->Format == MESA_FORMAT_Z24_S8) {
587
         for (i = 0; i < count; i++) {
588
            if (!mask || mask[i]) {
589
               temp[i] = (temp[i] & 0xffffff00) | src[i];
590
            }
591
         }
592
      }
593
      else {
594
         assert(dsrb->Format == MESA_FORMAT_S8_Z24);
595
         for (i = 0; i < count; i++) {
596
            if (!mask || mask[i]) {
597
               temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
598
            }
599
         }
600
      }
601
      dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
602
   }
603
}
604
 
605
static void
606
put_mono_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
607
                   const GLint x[], const GLint y[],
608
                   const void *value, const GLubyte *mask)
609
{
610
   struct gl_renderbuffer *dsrb = s8rb->Wrapped;
611
   GLuint temp[MAX_WIDTH], i;
612
   const GLubyte val = *((GLubyte *) value);
613
   /* get, modify, put */
614
   dsrb->GetValues(ctx, dsrb, count, x, y, temp);
615
   if (dsrb->Format == MESA_FORMAT_Z24_S8) {
616
      for (i = 0; i < count; i++) {
617
         if (!mask || mask[i]) {
618
            temp[i] = (temp[i] & 0xffffff00) | val;
619
         }
620
      }
621
   }
622
   else {
623
      assert(dsrb->Format == MESA_FORMAT_S8_Z24);
624
      for (i = 0; i < count; i++) {
625
         if (!mask || mask[i]) {
626
            temp[i] = (temp[i] & 0xffffff) | (val << 24);
627
         }
628
      }
629
   }
630
   dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
631
}
632
 
633
 
634
/**
635
 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
636
 * a stencil renderbuffer.
637
 * \return new stencil renderbuffer
638
 */
639
struct gl_renderbuffer *
640
_mesa_new_s8_renderbuffer_wrapper(struct gl_context *ctx, struct gl_renderbuffer *dsrb)
641
{
642
   struct gl_renderbuffer *s8rb;
643
 
644
   ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
645
          dsrb->Format == MESA_FORMAT_S8_Z24);
646
   ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
647
 
648
   s8rb = ctx->Driver.NewRenderbuffer(ctx, 0);
649
   if (!s8rb)
650
      return NULL;
651
 
652
   /* NOTE: need to do manual refcounting here */
653
   s8rb->Wrapped = dsrb;
654
   dsrb->RefCount++;
655
 
656
   s8rb->Name = dsrb->Name;
657
   s8rb->RefCount = 0;
658
   s8rb->Width = dsrb->Width;
659
   s8rb->Height = dsrb->Height;
660
   s8rb->InternalFormat = GL_STENCIL_INDEX8_EXT;
661
   s8rb->Format = MESA_FORMAT_S8;
662
   s8rb->_BaseFormat = GL_STENCIL_INDEX;
663
   s8rb->DataType = GL_UNSIGNED_BYTE;
664
   s8rb->Data = NULL;
665
   s8rb->Delete = delete_wrapper;
666
   s8rb->AllocStorage = alloc_wrapper_storage;
667
   s8rb->GetPointer = nop_get_pointer;
668
   s8rb->GetRow = get_row_s8;
669
   s8rb->GetValues = get_values_s8;
670
   s8rb->PutRow = put_row_s8;
671
   s8rb->PutRowRGB = NULL;
672
   s8rb->PutMonoRow = put_mono_row_s8;
673
   s8rb->PutValues = put_values_s8;
674
   s8rb->PutMonoValues = put_mono_values_s8;
675
 
676
   return s8rb;
677
}
678
 
679
 
680
 
681
/**
682
 ** The following functions are useful for hardware drivers that only
683
 ** implement combined depth/stencil buffers.
684
 ** The GL_EXT_framebuffer_object extension allows indepedent depth and
685
 ** stencil buffers to be used in any combination.
686
 ** Therefore, we sometimes have to merge separate depth and stencil
687
 ** renderbuffers into a single depth+stencil renderbuffer.  And sometimes
688
 ** we have to split combined depth+stencil renderbuffers into separate
689
 ** renderbuffers.
690
 **/
691
 
692
 
693
/**
694
 * Extract stencil values from the combined depth/stencil renderbuffer, storing
695
 * the values into a separate stencil renderbuffer.
696
 * \param dsRb  the source depth/stencil renderbuffer
697
 * \param stencilRb  the destination stencil renderbuffer
698
 *                   (either 8-bit or 32-bit)
699
 */
700
void
701
_mesa_extract_stencil(struct gl_context *ctx,
702
                      struct gl_renderbuffer *dsRb,
703
                      struct gl_renderbuffer *stencilRb)
704
{
705
   GLuint row, width, height;
706
 
707
   ASSERT(dsRb);
708
   ASSERT(stencilRb);
709
 
710
   ASSERT(dsRb->Format == MESA_FORMAT_Z24_S8);
711
   ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
712
   ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8 ||
713
          stencilRb->Format == MESA_FORMAT_S8);
714
   ASSERT(dsRb->Width == stencilRb->Width);
715
   ASSERT(dsRb->Height == stencilRb->Height);
716
 
717
   width = dsRb->Width;
718
   height = dsRb->Height;
719
 
720
   for (row = 0; row < height; row++) {
721
      GLuint depthStencil[MAX_WIDTH];
722
      dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
723
      if (stencilRb->Format == MESA_FORMAT_S8) {
724
         /* 8bpp stencil */
725
         GLubyte stencil[MAX_WIDTH];
726
         GLuint i;
727
         for (i = 0; i < width; i++) {
728
            stencil[i] = depthStencil[i] & 0xff;
729
         }
730
         stencilRb->PutRow(ctx, stencilRb, width, 0, row, stencil, NULL);
731
      }
732
      else {
733
         /* 32bpp stencil */
734
         /* the 24 depth bits will be ignored */
735
         ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8);
736
         ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
737
         stencilRb->PutRow(ctx, stencilRb, width, 0, row, depthStencil, NULL);
738
      }
739
   }
740
}
741
 
742
 
743
/**
744
 * Copy stencil values from a stencil renderbuffer into a combined
745
 * depth/stencil renderbuffer.
746
 * \param dsRb  the destination depth/stencil renderbuffer
747
 * \param stencilRb  the source stencil buffer (either 8-bit or 32-bit)
748
 */
749
void
750
_mesa_insert_stencil(struct gl_context *ctx,
751
                     struct gl_renderbuffer *dsRb,
752
                     struct gl_renderbuffer *stencilRb)
753
{
754
   GLuint row, width, height;
755
 
756
   ASSERT(dsRb);
757
   ASSERT(stencilRb);
758
 
759
   ASSERT(dsRb->Format == MESA_FORMAT_Z24_S8);
760
   ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
761
   ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8 ||
762
          stencilRb->Format == MESA_FORMAT_S8);
763
 
764
   ASSERT(dsRb->Width == stencilRb->Width);
765
   ASSERT(dsRb->Height == stencilRb->Height);
766
 
767
   width = dsRb->Width;
768
   height = dsRb->Height;
769
 
770
   for (row = 0; row < height; row++) {
771
      GLuint depthStencil[MAX_WIDTH];
772
 
773
      dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
774
 
775
      if (stencilRb->Format == MESA_FORMAT_S8) {
776
         /* 8bpp stencil */
777
         GLubyte stencil[MAX_WIDTH];
778
         GLuint i;
779
         stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
780
         for (i = 0; i < width; i++) {
781
            depthStencil[i] = (depthStencil[i] & 0xffffff00) | stencil[i];
782
         }
783
      }
784
      else {
785
         /* 32bpp stencil buffer */
786
         GLuint stencil[MAX_WIDTH], i;
787
         ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8);
788
         ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
789
         stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
790
         for (i = 0; i < width; i++) {
791
            depthStencil[i]
792
               = (depthStencil[i] & 0xffffff00) | (stencil[i] & 0xff);
793
         }
794
      }
795
 
796
      dsRb->PutRow(ctx, dsRb, width, 0, row, depthStencil, NULL);
797
   }
798
}
799
 
800
 
801
/**
802
 * Convert the stencil buffer from 8bpp to 32bpp depth/stencil.
803
 * \param stencilRb  the stencil renderbuffer to promote
804
 */
805
void
806
_mesa_promote_stencil(struct gl_context *ctx, struct gl_renderbuffer *stencilRb)
807
{
808
   const GLsizei width = stencilRb->Width;
809
   const GLsizei height = stencilRb->Height;
810
   GLubyte *data;
811
   GLint i, j, k;
812
 
813
   ASSERT(stencilRb->Format == MESA_FORMAT_S8);
814
   ASSERT(stencilRb->Data);
815
 
816
   data = (GLubyte *) stencilRb->Data;
817
   stencilRb->Data = NULL;
818
   stencilRb->AllocStorage(ctx, stencilRb, GL_DEPTH24_STENCIL8_EXT,
819
                           width, height);
820
 
821
   ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
822
 
823
   k = 0;
824
   for (i = 0; i < height; i++) {
825
      GLuint depthStencil[MAX_WIDTH];
826
      for (j = 0; j < width; j++) {
827
         depthStencil[j] = data[k++];
828
      }
829
      stencilRb->PutRow(ctx, stencilRb, width, 0, i, depthStencil, NULL);
830
   }
831
   free(data);
832
}