Subversion Repositories Kolibri OS

Rev

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

  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. }
  833.