Пример #1
0
/*
 * Draw stencil image.
 */
static void
draw_stencil_pixels( struct gl_context *ctx, GLint x, GLint y,
                     GLsizei width, GLsizei height,
                     GLenum type,
                     const struct gl_pixelstore_attrib *unpack,
                     const GLvoid *pixels )
{
   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
   const GLenum destType = GL_UNSIGNED_BYTE;
   GLint row;
   GLubyte *values;

   values = malloc(width * sizeof(GLubyte));
   if (!values) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
      return;
   }

   for (row = 0; row < height; row++) {
      const GLvoid *source = _mesa_image_address2d(unpack, pixels,
                                                   width, height,
                                                   GL_STENCIL_INDEX, type,
                                                   row, 0);
      _mesa_unpack_stencil_span(ctx, width, destType, values,
                                type, source, unpack,
                                ctx->_ImageTransferState);
      if (zoom) {
         _swrast_write_zoomed_stencil_span(ctx, x, y, width,
                                           x, y, values);
      }
      else {
         _swrast_write_stencil_span(ctx, width, x, y, values);
      }

      y++;
   }

   free(values);
}
Пример #2
0
/*
 * Draw stencil image.
 */
static void
draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
                     GLsizei width, GLsizei height,
                     GLenum type,
                     const struct gl_pixelstore_attrib *unpack,
                     const GLvoid *pixels )
{
   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
   GLint skipPixels;

   /* if width > MAX_WIDTH, have to process image in chunks */
   skipPixels = 0;
   while (skipPixels < width) {
      const GLint spanX = x + skipPixels;
      const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
      GLint row;
      for (row = 0; row < height; row++) {
         const GLint spanY = y + row;
         GLstencil values[MAX_WIDTH];
         GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
                         ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
         const GLvoid *source = _mesa_image_address2d(unpack, pixels,
                                                      width, height,
                                                      GL_COLOR_INDEX, type,
                                                      row, skipPixels);
         _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
                                   type, source, unpack,
                                   ctx->_ImageTransferState);
         if (zoom) {
            _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth,
                                              spanX, spanY, values);
         }
         else {
            _swrast_write_stencil_span(ctx, spanWidth, spanX, spanY, values);
         }
      }
      skipPixels += spanWidth;
   }
}
Пример #3
0
/**
 * This isn't terribly efficient.  If a driver really has combined
 * depth/stencil buffers the driver should implement an optimized
 * CopyPixels function.
 */
static void
copy_depth_stencil_pixels(GLcontext *ctx,
                          const GLint srcX, const GLint srcY,
                          const GLint width, const GLint height,
                          const GLint destX, const GLint destY)
{
   struct gl_renderbuffer *stencilReadRb, *depthReadRb, *depthDrawRb;
   GLint sy, dy, stepy;
   GLint j;
   GLstencil *tempStencilImage = NULL, *stencilPtr = NULL;
   GLfloat *tempDepthImage = NULL, *depthPtr = NULL;
   const GLfloat depthScale = ctx->DrawBuffer->_DepthMaxF;
   const GLuint stencilMask = ctx->Stencil.WriteMask[0];
   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
   const GLboolean shiftOrOffset
      = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
   const GLboolean scaleOrBias
      = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
   GLint overlapping;

   depthDrawRb = ctx->DrawBuffer->_DepthBuffer;
   depthReadRb = ctx->ReadBuffer->_DepthBuffer;
   stencilReadRb = ctx->ReadBuffer->_StencilBuffer;

   ASSERT(depthDrawRb);
   ASSERT(depthReadRb);
   ASSERT(stencilReadRb);

   /* Determine if copy should be bottom-to-top or top-to-bottom */
   if (srcY < destY) {
      /* top-down  max-to-min */
      sy = srcY + height - 1;
      dy = destY + height - 1;
      stepy = -1;
   }
   else {
      /* bottom-up  min-to-max */
      sy = srcY;
      dy = destY;
      stepy = 1;
   }

   if (ctx->DrawBuffer == ctx->ReadBuffer) {
      overlapping = regions_overlap(srcX, srcY, destX, destY, width, height,
                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
   }
   else {
      overlapping = GL_FALSE;
   }

   if (overlapping) {
      GLint ssy = sy;

      if (stencilMask != 0x0) {
         tempStencilImage
            = (GLstencil *) _mesa_malloc(width * height * sizeof(GLstencil));
         if (!tempStencilImage) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
            return;
         }

         /* get copy of stencil pixels */
         stencilPtr = tempStencilImage;
         for (j = 0; j < height; j++, ssy += stepy) {
            _swrast_read_stencil_span(ctx, stencilReadRb,
                                      width, srcX, ssy, stencilPtr);
            stencilPtr += width;
         }
         stencilPtr = tempStencilImage;
      }

      if (ctx->Depth.Mask) {
         tempDepthImage
            = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat));
         if (!tempDepthImage) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
            _mesa_free(tempStencilImage);
            return;
         }

         /* get copy of depth pixels */
         depthPtr = tempDepthImage;
         for (j = 0; j < height; j++, ssy += stepy) {
            _swrast_read_depth_span_float(ctx, depthReadRb,
                                          width, srcX, ssy, depthPtr);
            depthPtr += width;
         }
         depthPtr = tempDepthImage;
      }
   }

   for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
      if (stencilMask != 0x0) {
         GLstencil stencil[MAX_WIDTH];

         /* Get stencil values */
         if (overlapping) {
            _mesa_memcpy(stencil, stencilPtr, width * sizeof(GLstencil));
            stencilPtr += width;
         }
         else {
            _swrast_read_stencil_span(ctx, stencilReadRb,
                                      width, srcX, sy, stencil);
         }

         /* Apply shift, offset, look-up table */
         if (shiftOrOffset) {
            _mesa_shift_and_offset_stencil(ctx, width, stencil);
         }
         if (ctx->Pixel.MapStencilFlag) {
            _mesa_map_stencil(ctx, width, stencil);
         }

         /* Write values */
         if (zoom) {
            _swrast_write_zoomed_stencil_span(ctx, destX, destY, width,
                                              destX, dy, stencil);
         }
         else {
            _swrast_write_stencil_span( ctx, width, destX, dy, stencil );
         }
      }

      if (ctx->Depth.Mask) {
         GLfloat depth[MAX_WIDTH];
         GLuint zVals32[MAX_WIDTH];
         GLushort zVals16[MAX_WIDTH];
         GLvoid *zVals;
         GLuint zBytes;

         /* get depth values */
         if (overlapping) {
            _mesa_memcpy(depth, depthPtr, width * sizeof(GLfloat));
            depthPtr += width;
         }
         else {
            _swrast_read_depth_span_float(ctx, depthReadRb,
                                          width, srcX, sy, depth);
         }

         /* scale & bias */
         if (scaleOrBias) {
            _mesa_scale_and_bias_depth(ctx, width, depth);
         }
         /* convert to integer Z values */
         if (depthDrawRb->DataType == GL_UNSIGNED_SHORT) {
            GLint k;
            for (k = 0; k < width; k++)
               zVals16[k] = (GLushort) (depth[k] * depthScale);
            zVals = zVals16;
            zBytes = 2;
         }
         else {
            GLint k;
            for (k = 0; k < width; k++)
               zVals32[k] = (GLuint) (depth[k] * depthScale);
            zVals = zVals32;
            zBytes = 4;
         }

         /* Write values */
         if (zoom) {
            _swrast_write_zoomed_z_span(ctx, destX, destY, width,
                                        destX, dy, zVals);
         }
         else {
            _swrast_put_row(ctx, depthDrawRb, width, destX, dy, zVals, zBytes);
         }
      }
   }

   if (tempStencilImage)
      _mesa_free(tempStencilImage);

   if (tempDepthImage)
      _mesa_free(tempDepthImage);
}
Пример #4
0
static void
copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
                     GLint width, GLint height,
                     GLint destx, GLint desty )
{
   struct gl_framebuffer *fb = ctx->ReadBuffer;
   struct gl_renderbuffer *rb = fb->_StencilBuffer;
   GLint sy, dy, stepy;
   GLint j;
   GLstencil *p, *tmpImage;
   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
   const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
   GLint overlapping;

   if (!rb) {
      /* no readbuffer - OK */
      return;
   }

   /* Determine if copy should be bottom-to-top or top-to-bottom */
   if (srcy < desty) {
      /* top-down  max-to-min */
      sy = srcy + height - 1;
      dy = desty + height - 1;
      stepy = -1;
   }
   else {
      /* bottom-up  min-to-max */
      sy = srcy;
      dy = desty;
      stepy = 1;
   }

   if (ctx->DrawBuffer == ctx->ReadBuffer) {
      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
   }
   else {
      overlapping = GL_FALSE;
   }

   if (overlapping) {
      GLint ssy = sy;
      tmpImage = (GLstencil *) _mesa_malloc(width * height * sizeof(GLstencil));
      if (!tmpImage) {
         _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
         return;
      }
      p = tmpImage;
      for (j = 0; j < height; j++, ssy += stepy) {
         _swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p );
         p += width;
      }
      p = tmpImage;
   }
   else {
      tmpImage = NULL;  /* silence compiler warning */
      p = NULL;
   }

   for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
      GLstencil stencil[MAX_WIDTH];

      /* Get stencil values */
      if (overlapping) {
         _mesa_memcpy(stencil, p, width * sizeof(GLstencil));
         p += width;
      }
      else {
         _swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil );
      }

      /* Apply shift, offset, look-up table */
      if (shift_or_offset) {
         _mesa_shift_and_offset_stencil( ctx, width, stencil );
      }
      if (ctx->Pixel.MapStencilFlag) {
         _mesa_map_stencil( ctx, width, stencil );
      }

      /* Write stencil values */
      if (zoom) {
         _swrast_write_zoomed_stencil_span(ctx, destx, desty, width,
                                           destx, dy, stencil);
      }
      else {
         _swrast_write_stencil_span( ctx, width, destx, dy, stencil );
      }
   }

   if (overlapping)
      _mesa_free(tmpImage);
}
Пример #5
0
/*
 * Draw stencil image.
 */
static void
draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
                     GLsizei width, GLsizei height,
                     GLenum type,
                     const struct gl_pixelstore_attrib *unpack,
                     const GLvoid *pixels )
{
   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
   const GLint desty = y;
   GLint row, skipPixels;

   if (type != GL_BYTE &&
       type != GL_UNSIGNED_BYTE &&
       type != GL_SHORT &&
       type != GL_UNSIGNED_SHORT &&
       type != GL_INT &&
       type != GL_UNSIGNED_INT &&
       type != GL_FLOAT &&
       type != GL_BITMAP) {
      _mesa_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)");
      return;
   }

   if (ctx->Visual.stencilBits == 0) {
      _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawPixels(no stencil buffer)");
      return;
   }

   /* if width > MAX_WIDTH, have to process image in chunks */
   skipPixels = 0;
   while (skipPixels < width) {
      const GLint spanX = x;
      GLint spanY = y;
      const GLint spanWidth = (width - skipPixels > MAX_WIDTH)
                            ? MAX_WIDTH : (width - skipPixels);

      for (row = 0; row < height; row++, spanY++) {
         GLstencil values[MAX_WIDTH];
         GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
                         ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
         const GLvoid *source = _mesa_image_address2d(unpack, pixels,
                                                      width, height,
                                                      GL_COLOR_INDEX, type,
                                                      row, skipPixels);
         _mesa_unpack_index_span(ctx, spanWidth, destType, values,
                                 type, source, unpack,
                                 ctx->_ImageTransferState);
         if (ctx->_ImageTransferState & IMAGE_SHIFT_OFFSET_BIT) {
            _mesa_shift_and_offset_stencil(ctx, spanWidth, values);
         }
         if (ctx->Pixel.MapStencilFlag) {
            _mesa_map_stencil(ctx, spanWidth, values);
         }

         if (zoom) {
            _swrast_write_zoomed_stencil_span(ctx, (GLuint) spanWidth,
                                            spanX, spanY, values, desty, 0);
         }
         else {
            _swrast_write_stencil_span(ctx, (GLuint) spanWidth,
                                     spanX, spanY, values);
         }
      }
      skipPixels += spanWidth;
   }
}
Пример #6
0
static void
copy_stencil_pixels( struct gl_context *ctx, GLint srcx, GLint srcy,
                     GLint width, GLint height,
                     GLint destx, GLint desty )
{
    struct gl_framebuffer *fb = ctx->ReadBuffer;
    struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
    GLint sy, dy, stepy;
    GLint j;
    GLubyte *p, *tmpImage, *stencil;
    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
    GLint overlapping;

    if (!rb) {
        /* no readbuffer - OK */
        return;
    }

    if (ctx->DrawBuffer == ctx->ReadBuffer) {
        overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
                                      ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
    }
    else {
        overlapping = GL_FALSE;
    }

    /* Determine if copy should be bottom-to-top or top-to-bottom */
    if (!overlapping && srcy < desty) {
        /* top-down  max-to-min */
        sy = srcy + height - 1;
        dy = desty + height - 1;
        stepy = -1;
    }
    else {
        /* bottom-up  min-to-max */
        sy = srcy;
        dy = desty;
        stepy = 1;
    }

    if (overlapping) {
        GLint ssy = sy;
        tmpImage = malloc(width * height * sizeof(GLubyte));
        if (!tmpImage) {
            _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
            return;
        }
        p = tmpImage;
        for (j = 0; j < height; j++, ssy += stepy) {
            _swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p );
            p += width;
        }
        p = tmpImage;
    }
    else {
        tmpImage = NULL;  /* silence compiler warning */
        p = NULL;
    }

    stencil = malloc(width * sizeof(GLubyte));
    if (!stencil) {
        _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels()");
        goto end;
    }

    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
        /* Get stencil values */
        if (overlapping) {
            memcpy(stencil, p, width * sizeof(GLubyte));
            p += width;
        }
        else {
            _swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil );
        }

        _mesa_apply_stencil_transfer_ops(ctx, width, stencil);

        /* Write stencil values */
        if (zoom) {
            _swrast_write_zoomed_stencil_span(ctx, destx, desty, width,
                                              destx, dy, stencil);
        }
        else {
            _swrast_write_stencil_span( ctx, width, destx, dy, stencil );
        }
    }

    free(stencil);

end:
    if (overlapping)
        free(tmpImage);
}