Beispiel #1
0
static void
map_attachment(struct gl_context *ctx,
                 struct gl_framebuffer *fb,
                 gl_buffer_index buffer)
{
   struct gl_texture_object *texObj = fb->Attachment[buffer].Texture;
   struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer;
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);

   if (texObj) {
      /* map texture image (render to texture) */
      const GLuint level = fb->Attachment[buffer].TextureLevel;
      const GLuint face = fb->Attachment[buffer].CubeMapFace;
      const GLuint slice = fb->Attachment[buffer].Zoffset;
      struct gl_texture_image *texImage = texObj->Image[face][level];
      if (texImage) {
         ctx->Driver.MapTextureImage(ctx, texImage, slice,
                                     0, 0, texImage->Width, texImage->Height,
                                     GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
                                     &srb->Map, &srb->RowStride);
      }
   }
   else if (rb) {
      /* Map ordinary renderbuffer */
      ctx->Driver.MapRenderbuffer(ctx, rb,
                                  0, 0, rb->Width, rb->Height,
                                  GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
                                  &srb->Map, &srb->RowStride);
   }

   assert(srb->Map);
}
Beispiel #2
0
/**
 * Put an array of 32-bit z values into the depth buffer.
 * Note: the z values are always in the range [0, 2^32-1].
 */
static void
put_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
               GLuint count, const GLint x[], const GLint y[],
               const GLuint zvalues[], const GLubyte mask[])
{
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   const GLint w = rb->Width, h = rb->Height;
   GLubyte *map = _swrast_pixel_address(rb, 0, 0);
   GLuint i;

   if (rb->Format == MESA_FORMAT_Z_UNORM32) {
      const GLint rowStride = srb->RowStride;
      for (i = 0; i < count; i++) {
         if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
            GLuint *dst = (GLuint *) (map + y[i] * rowStride + x[i] * 4);
            *dst = zvalues[i];
         }
      }
   }
   else {
      gl_pack_uint_z_func packZ = _mesa_get_pack_uint_z_func(rb->Format);
      const GLint bpp = _mesa_get_format_bytes(rb->Format);
      const GLint rowStride = srb->RowStride;
      for (i = 0; i < count; i++) {
         if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
            void *dst = map + y[i] * rowStride + x[i] * bpp;
            packZ(zvalues + i, dst);
         }
      }
   }
}
Beispiel #3
0
/**
 * Return the depth buffer associated with an OSMesa context.
 * Input:  c - the OSMesa context
 * Output:  width, height - size of buffer in pixels
 *          bytesPerValue - bytes per depth value (2 or 4)
 *          buffer - pointer to depth buffer values
 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
 */
GLAPI GLboolean GLAPIENTRY
OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
                      GLint *bytesPerValue, void **buffer )
{
   struct swrast_renderbuffer *srb = NULL;

   if (c->gl_buffer)
      srb = swrast_renderbuffer(c->gl_buffer->
                                Attachment[BUFFER_DEPTH].Renderbuffer);

   if (!srb || !srb->Buffer) {
      *width = 0;
      *height = 0;
      *bytesPerValue = 0;
      *buffer = 0;
      return GL_FALSE;
   }
   else {
      *width = srb->Base.Width;
      *height = srb->Base.Height;
      if (c->gl_visual->depthBits <= 16)
         *bytesPerValue = sizeof(GLushort);
      else
         *bytesPerValue = sizeof(GLuint);
      *buffer = (void *) srb->Buffer;
      return GL_TRUE;
   }
}
Beispiel #4
0
static void
unmap_attachment(struct gl_context *ctx,
                   struct gl_framebuffer *fb,
                   gl_buffer_index buffer)
{
   struct gl_texture_object *texObj = fb->Attachment[buffer].Texture;
   struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer;
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);

   if (texObj) {
      /* unmap texture image (render to texture) */
      const GLuint level = fb->Attachment[buffer].TextureLevel;
      const GLuint face = fb->Attachment[buffer].CubeMapFace;
      const GLuint slice = fb->Attachment[buffer].Zoffset;
      struct gl_texture_image *texImage = texObj->Image[face][level];
      if (texImage) {
         ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
      }
   }
   else if (rb) {
      /* unmap ordinary renderbuffer */
      ctx->Driver.UnmapRenderbuffer(ctx, rb);
   }

   srb->Map = NULL;
}
Beispiel #5
0
/**
 * Update the renderbuffer wrapper for rendering to a texture.
 * For example, update the width, height of the RB based on the texture size,
 * update the internal format info, etc.
 */
static void
update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
{
   struct gl_renderbuffer *rb = att->Renderbuffer;
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   struct swrast_texture_image *swImage;
   gl_format format;
   GLuint zOffset;

   (void) ctx;

   swImage = swrast_texture_image(rb->TexImage);
   assert(swImage);

   format = swImage->Base.TexFormat;

   if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
      zOffset = 0;
   }
   else {
      zOffset = att->Zoffset;
   }

   /* Want to store linear values, not sRGB */
   rb->Format = _mesa_get_srgb_format_linear(format);

   srb->Buffer = swImage->ImageSlices[zOffset];
}
Beispiel #6
0
/**
 * Get array of 32-bit z values from the depth buffer.  With clipping.
 * Note: the returned values are always in the range [0, 2^32-1].
 */
static void
get_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
               GLuint count, const GLint x[], const GLint y[],
               GLuint zbuffer[])
{
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   const GLint w = rb->Width, h = rb->Height;
   const GLubyte *map = _swrast_pixel_address(rb, 0, 0);
   GLuint i;

   if (rb->Format == MESA_FORMAT_Z_UNORM32) {
      const GLint rowStride = srb->RowStride;
      for (i = 0; i < count; i++) {
         if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
            zbuffer[i] = *((GLuint *) (map + y[i] * rowStride + x[i] * 4));
         }
      }
   }
   else {
      const GLint bpp = _mesa_get_format_bytes(rb->Format);
      const GLint rowStride = srb->RowStride;
      for (i = 0; i < count; i++) {
         if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
            const GLubyte *src = map + y[i] * rowStride+ x[i] * bpp;
            _mesa_unpack_uint_z_row(rb->Format, 1, src, &zbuffer[i]);
         }
      }
   }
}
Beispiel #7
0
/**
 * Called via gl_renderbuffer::Delete()
 */
static void
soft_renderbuffer_delete(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);

   free(srb->Buffer);
   srb->Buffer = NULL;
   _mesa_delete_renderbuffer(ctx, rb);
}
Beispiel #8
0
/**
 * Do software-based glCopyPixels.
 * By time we get here, all parameters will have been error-checked.
 */
void
_swrast_CopyPixels( struct gl_context *ctx,
                    GLint srcx, GLint srcy, GLsizei width, GLsizei height,
                    GLint destx, GLint desty, GLenum type )
{
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    struct gl_renderbuffer *rb;

    if (!_mesa_check_conditional_render(ctx))
        return; /* don't copy */

    if (swrast->NewState)
        _swrast_validate_derived( ctx );

    if (!(SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 ||
            ctx->Pixel.ZoomX != 1.0F ||
            ctx->Pixel.ZoomY != 1.0F ||
            ctx->_ImageTransferState) &&
            swrast_fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty,
                                    type)) {
        /* all done */
        return;
    }

    swrast_render_start(ctx);
    rb = map_readbuffer(ctx, type);

    switch (type) {
    case GL_COLOR:
        copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
        break;
    case GL_DEPTH:
        copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
        break;
    case GL_STENCIL:
        copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
        break;
    case GL_DEPTH_STENCIL_EXT:
        /* Copy buffers separately (if the fast copy path wasn't taken) */
        copy_depth_pixels(ctx, srcx, srcy, width, height, destx, desty);
        copy_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty);
        break;
    default:
        _mesa_problem(ctx, "unexpected type in _swrast_CopyPixels");
    }

    swrast_render_finish(ctx);

    if (rb) {
        struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
        ctx->Driver.UnmapRenderbuffer(ctx, rb);
        srb->Map = NULL;
    }
}
Beispiel #9
0
static void
sw_bb_renderbuffer_delete(struct gl_renderbuffer *rb)
{
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);

    if (srb->Buffer)
    {
        HeapFree(GetProcessHeap(), 0, srb->Buffer);
        srb->Buffer = NULL;
    }
}
Beispiel #10
0
static void
dri_swap_buffers(__DRIdrawable * dPriv)
{
    __DRIscreen *sPriv = dPriv->driScreenPriv;

    GET_CURRENT_CONTEXT(ctx);

    struct dri_drawable *drawable = dri_drawable(dPriv);
    struct gl_framebuffer *fb;
    struct swrast_renderbuffer *frontrb, *backrb;

    TRACE;

    fb = &drawable->Base;

    frontrb =
	swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
    backrb =
	swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);

    /* check for signle-buffered */
    if (backrb == NULL)
	return;

    /* check if swapping currently bound buffer */
    if (ctx && ctx->DrawBuffer == fb) {
	/* flush pending rendering */
	_mesa_notifySwapBuffers(ctx);
    }

    sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
				   0, 0,
				   frontrb->Base.Width,
				   frontrb->Base.Height,
				   backrb->Base.Data,
				   dPriv->loaderPrivate);
}
Beispiel #11
0
static void
swrast_map_renderbuffer(struct gl_context *ctx,
			struct gl_renderbuffer *rb,
			GLuint x, GLuint y, GLuint w, GLuint h,
			GLbitfield mode,
			GLubyte **out_map,
			GLint *out_stride)
{
   struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
   GLubyte *map = rb->Data;
   int cpp = _mesa_get_format_bytes(rb->Format);
   int stride = rb->RowStride * cpp;

   if (rb->AllocStorage == swrast_alloc_front_storage) {
      __DRIdrawable *dPriv = xrb->dPriv;
      __DRIscreen *sPriv = dPriv->driScreenPriv;

      xrb->map_mode = mode;
      xrb->map_x = x;
      xrb->map_y = y;
      xrb->map_w = w;
      xrb->map_h = h;

      stride = w * cpp;
      rb->Data = malloc(h * stride);

      sPriv->swrast_loader->getImage(dPriv, x, y, w, h,
				     (char *)rb->Data,
				     dPriv->loaderPrivate);

      *out_map = rb->Data;
      *out_stride = stride;
      return;
   }

   ASSERT(rb->Data);

   if (rb->AllocStorage == swrast_alloc_back_storage) {
      map += (rb->Height - 1) * stride;
      stride = -stride;
   }

   map += (GLsizei)y * stride;
   map += (GLsizei)x * cpp;

   *out_map = map;
   *out_stride = stride;
}
Beispiel #12
0
static GLboolean
swrast_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
			  GLenum internalFormat, GLuint width, GLuint height)
{
    struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);

    TRACE;

    free(rb->Data);

    swrast_alloc_front_storage(ctx, rb, internalFormat, width, height);

    rb->Data = malloc(height * xrb->pitch);

    return GL_TRUE;
}
Beispiel #13
0
/**
 * Determine what type to use (ubyte vs. float) for span colors for the
 * given renderbuffer.
 * See also _swrast_write_rgba_span().
 */
static void
find_renderbuffer_colortype(struct gl_renderbuffer *rb)
{
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   GLuint rbMaxBits = _mesa_get_format_max_bits(rb->Format);
   GLenum rbDatatype = _mesa_get_format_datatype(rb->Format);

   if (rbDatatype == GL_UNSIGNED_NORMALIZED && rbMaxBits <= 8) {
      /* the buffer's values fit in GLubyte values */
      srb->ColorType = GL_UNSIGNED_BYTE;
   }
   else {
      /* use floats otherwise */
      srb->ColorType = GL_FLOAT;
   }
}
Beispiel #14
0
static GLboolean
swrast_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
			   GLenum internalFormat, GLuint width, GLuint height)
{
    struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);

    TRACE;

    rb->Data = NULL;
    rb->Width = width;
    rb->Height = height;

    xrb->pitch = bytes_per_line(width * xrb->bpp, 32);

    return GL_TRUE;
}
Beispiel #15
0
/**
 * Update the renderbuffer wrapper for rendering to a texture.
 * For example, update the width, height of the RB based on the texture size,
 * update the internal format info, etc.
 */
static void
update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
{
   struct gl_renderbuffer *rb = att->Renderbuffer;
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   struct swrast_texture_image *swImage;
   gl_format format;
   GLuint zOffset;

   (void) ctx;

   swImage = swrast_texture_image(_mesa_get_attachment_teximage(att));
   assert(swImage);

   format = swImage->Base.TexFormat;

   if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
      zOffset = 0;
   }
   else {
      zOffset = att->Zoffset;
   }

   rb->Width = swImage->Base.Width;
   rb->Height = swImage->Base.Height;
   rb->InternalFormat = swImage->Base.InternalFormat;
   rb->_BaseFormat = _mesa_get_format_base_format(format);

   /* Want to store linear values, not sRGB */
   rb->Format = _mesa_get_srgb_format_linear(format);
 
   /* Set the gl_renderbuffer::Buffer field so that mapping the buffer
    * succeeds.
     */
   if (att->Texture->Target == GL_TEXTURE_3D ||
       att->Texture->Target == GL_TEXTURE_2D_ARRAY_EXT) {
      srb->Buffer = swImage->Buffer +
         swImage->ImageOffsets[zOffset] * _mesa_get_format_bytes(format);
   }
   else {
      srb->Buffer = swImage->Buffer;
   }
}
Beispiel #16
0
static void
swrast_unmap_renderbuffer(struct gl_context *ctx,
			  struct gl_renderbuffer *rb)
{
   struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);

   if (rb->AllocStorage == swrast_alloc_front_storage) {
      __DRIdrawable *dPriv = xrb->dPriv;
      __DRIscreen *sPriv = dPriv->driScreenPriv;

      if (xrb->map_mode & GL_MAP_WRITE_BIT) {
	 sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_DRAW,
					xrb->map_x, xrb->map_y,
					xrb->map_w, xrb->map_h,
					rb->Data,
					dPriv->loaderPrivate);
      }

      free(rb->Data);
      rb->Data = NULL;
   }
}
Beispiel #17
0
/* Renderbuffer routines */
static GLboolean
sw_bb_renderbuffer_storage(struct gl_context* ctx, struct gl_renderbuffer *rb,
                          GLenum internalFormat,
                          GLuint width, GLuint height)
{
    struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
    struct sw_framebuffer* fb = CONTAINING_RECORD(srb, struct sw_framebuffer, backbuffer);
    UINT widthBytes = WIDTH_BYTES_ALIGN32(width, pixel_formats[fb->format_index].color_bits); 
    srb->Base.Format = pixel_formats[fb->format_index].mesa;

    if(srb->Buffer)
        srb->Buffer = HeapReAlloc(GetProcessHeap(), 0, srb->Buffer, widthBytes*height);
    else
        srb->Buffer = HeapAlloc(GetProcessHeap(), 0, widthBytes*height);
    if(!srb->Buffer)
    {
        srb->Base.Format = MESA_FORMAT_NONE;
        return GL_FALSE;
    }
    srb->Base.Width = width;
    srb->Base.Height = height;
    srb->RowStride = widthBytes;
    return GL_TRUE;
}
Beispiel #18
0
void
_swrast_map_soft_renderbuffer(struct gl_context *ctx,
                              struct gl_renderbuffer *rb,
                              GLuint x, GLuint y, GLuint w, GLuint h,
                              GLbitfield mode,
                              GLubyte **out_map,
                              GLint *out_stride)
{
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   GLubyte *map = srb->Buffer;
   int cpp = _mesa_get_format_bytes(rb->Format);
   int stride = rb->Width * cpp;

   if (!map) {
      *out_map = NULL;
      *out_stride = 0;
   }

   map += y * stride;
   map += x * cpp;

   *out_map = map;
   *out_stride = stride;
}
Beispiel #19
0
/**
 * Find/map the renderbuffer that we'll be reading from.
 * The swrast_render_start() function only maps the drawing buffers,
 * not the read buffer.
 */
static struct gl_renderbuffer *
map_readbuffer(struct gl_context *ctx, GLenum type)
{
    struct gl_framebuffer *fb = ctx->ReadBuffer;
    struct gl_renderbuffer *rb;
    struct swrast_renderbuffer *srb;

    switch (type) {
    case GL_COLOR:
        rb = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer;
        break;
    case GL_DEPTH:
    case GL_DEPTH_STENCIL:
        rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
        break;
    case GL_STENCIL:
        rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
        break;
    default:
        return NULL;
    }

    srb = swrast_renderbuffer(rb);

    if (!srb || srb->Map) {
        /* no buffer, or buffer is mapped already, we're done */
        return NULL;
    }

    ctx->Driver.MapRenderbuffer(ctx, rb,
                                0, 0, rb->Width, rb->Height,
                                GL_MAP_READ_BIT,
                                &srb->Map, &srb->RowStride);

    return rb;
}
Beispiel #20
0
static void
osmesa_MapRenderbuffer(struct gl_context *ctx,
                       struct gl_renderbuffer *rb,
                       GLuint x, GLuint y, GLuint w, GLuint h,
                       GLbitfield mode,
                       GLubyte **mapOut, GLint *rowStrideOut)
{
   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);

   if (rb->ClassID == OSMESA_RENDERBUFFER_CLASS) {
      /* this is an OSMesa renderbuffer which wraps user memory */
      struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
      const GLuint bpp = _mesa_get_format_bytes(rb->Format);
      GLint rowStride; /* in bytes */

      if (osmesa->userRowLength)
         rowStride = osmesa->userRowLength * bpp;
      else
         rowStride = rb->Width * bpp;

      if (!osmesa->yup) {
         /* Y=0 is top line of window */
         y = rb->Height - y - 1;
         *rowStrideOut = -rowStride;
      }
      else {
         *rowStrideOut = rowStride;
      }

      *mapOut = (GLubyte *) srb->Buffer + y * rowStride + x * bpp;
   }
   else {
      _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode,
                                    mapOut, rowStrideOut);
   }
}
Beispiel #21
0
/**
 * Read float RGBA pixels from a renderbuffer.  Clipping will be done to
 * prevent reading ouside the buffer's boundaries.
 * \param rgba  the returned colors
 */
void
_swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb,
                        GLuint n, GLint x, GLint y,
                        GLvoid *rgba)
{
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   GLenum dstType = GL_FLOAT;
   const GLint bufWidth = (GLint) rb->Width;
   const GLint bufHeight = (GLint) rb->Height;

   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
      /* completely above, below, or right */
      /* XXX maybe leave rgba values undefined? */
      memset(rgba, 0, 4 * n * sizeof(GLchan));
   }
   else {
      GLint skip, length;
      GLubyte *src;

      if (x < 0) {
         /* left edge clipping */
         skip = -x;
         length = (GLint) n - skip;
         if (length < 0) {
            /* completely left of window */
            return;
         }
         if (length > bufWidth) {
            length = bufWidth;
         }
      }
      else if ((GLint) (x + n) > bufWidth) {
         /* right edge clipping */
         skip = 0;
         length = bufWidth - x;
         if (length < 0) {
            /* completely to right of window */
            return;
         }
      }
      else {
         /* no clipping */
         skip = 0;
         length = (GLint) n;
      }

      ASSERT(rb);
      ASSERT(rb->_BaseFormat == GL_RGBA ||
	     rb->_BaseFormat == GL_RGB ||
	     rb->_BaseFormat == GL_RG ||
	     rb->_BaseFormat == GL_RED ||
	     rb->_BaseFormat == GL_LUMINANCE ||
	     rb->_BaseFormat == GL_INTENSITY ||
	     rb->_BaseFormat == GL_LUMINANCE_ALPHA ||
	     rb->_BaseFormat == GL_ALPHA);

      assert(srb->Map);

      src = _swrast_pixel_address(rb, x + skip, y);

      if (dstType == GL_UNSIGNED_BYTE) {
         _mesa_unpack_ubyte_rgba_row(rb->Format, length, src,
                                     (GLubyte (*)[4]) rgba + skip);
      }
      else if (dstType == GL_FLOAT) {
         _mesa_unpack_rgba_row(rb->Format, length, src,
                               (GLfloat (*)[4]) rgba + skip);
      }
      else {
         _mesa_problem(ctx, "unexpected type in _swrast_read_rgba_span()");
      }
   }
}
Beispiel #22
0
/**
 * Apply all the per-fragment operations to a span.
 * This now includes texturing (_swrast_write_texture_span() is history).
 * This function may modify any of the array values in the span.
 * span->interpMask and span->arrayMask may be changed but will be restored
 * to their original values before returning.
 */
void
_swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
{
   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
   const GLuint colorMask = *((GLuint *)ctx->Color.ColorMask);
   const GLbitfield origInterpMask = span->interpMask;
   const GLbitfield origArrayMask = span->arrayMask;
   const GLbitfield64 origArrayAttribs = span->arrayAttribs;
   const GLenum origChanType = span->array->ChanType;
   void * const origRgba = span->array->rgba;
   const GLboolean texture = ctx->Texture._EnabledCoord;
   struct gl_framebuffer *fb = ctx->DrawBuffer;

   /*
   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__,
          span->interpMask, span->arrayMask);
   */

   ASSERT(span->primitive == GL_POINT ||
          span->primitive == GL_LINE ||
	  span->primitive == GL_POLYGON ||
          span->primitive == GL_BITMAP);

   /* Fragment write masks */
   if (span->arrayMask & SPAN_MASK) {
      /* mask was initialized by caller, probably glBitmap */
      span->writeAll = GL_FALSE;
   }
   else {
      memset(span->array->mask, 1, span->end);
      span->writeAll = GL_TRUE;
   }

   /* Clip to window/scissor box */
   if (!clip_span(ctx, span)) {
      return;
   }

   ASSERT(span->end <= MAX_WIDTH);

   /* Depth bounds test */
   if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
      if (!_swrast_depth_bounds_test(ctx, span)) {
         return;
      }
   }

#ifdef DEBUG
   /* Make sure all fragments are within window bounds */
   if (span->arrayMask & SPAN_XY) {
      /* array of pixel locations */
      GLuint i;
      for (i = 0; i < span->end; i++) {
         if (span->array->mask[i]) {
            assert(span->array->x[i] >= fb->_Xmin);
            assert(span->array->x[i] < fb->_Xmax);
            assert(span->array->y[i] >= fb->_Ymin);
            assert(span->array->y[i] < fb->_Ymax);
         }
      }
   }
#endif

   /* Polygon Stippling */
   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
      stipple_polygon_span(ctx, span);
   }

   /* This is the normal place to compute the fragment color/Z
    * from texturing or shading.
    */
   if (texture && !swrast->_DeferredTexture) {
      shade_texture_span(ctx, span);
   }

   /* Do the alpha test */
   if (ctx->Color.AlphaEnabled) {
      if (!_swrast_alpha_test(ctx, span)) {
         /* all fragments failed test */
         goto end;
      }
   }

   /* Stencil and Z testing */
   if (ctx->Stencil._Enabled || ctx->Depth.Test) {
      if (!(span->arrayMask & SPAN_Z))
         _swrast_span_interpolate_z(ctx, span);

      if (ctx->Stencil._Enabled) {
         /* Combined Z/stencil tests */
         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
            /* all fragments failed test */
            goto end;
         }
      }
      else if (fb->Visual.depthBits > 0) {
         /* Just regular depth testing */
         ASSERT(ctx->Depth.Test);
         ASSERT(span->arrayMask & SPAN_Z);
         if (!_swrast_depth_test_span(ctx, span)) {
            /* all fragments failed test */
            goto end;
         }
      }
   }

   /* We had to wait until now to check for glColorMask(0,0,0,0) because of
    * the occlusion test.
    */
   if (colorMask == 0) {
      /* no colors to write */
      goto end;
   }

   /* If we were able to defer fragment color computation to now, there's
    * a good chance that many fragments will have already been killed by
    * Z/stencil testing.
    */
   if (texture && swrast->_DeferredTexture) {
      shade_texture_span(ctx, span);
   }

#if CHAN_BITS == 32
   if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
      interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
   }
#else
   if ((span->arrayMask & SPAN_RGBA) == 0) {
      interpolate_int_colors(ctx, span);
   }
#endif

   ASSERT(span->arrayMask & SPAN_RGBA);

   /* Fog */
   if (swrast->_FogEnabled) {
      _swrast_fog_rgba_span(ctx, span);
   }

   /* Antialias coverage application */
   if (span->arrayMask & SPAN_COVERAGE) {
      apply_aa_coverage(span);
   }

   /*
    * Write to renderbuffers.
    * Depending on glDrawBuffer() state and the which color outputs are
    * written by the fragment shader, we may either replicate one color to
    * all renderbuffers or write a different color to each renderbuffer.
    * multiFragOutputs=TRUE for the later case.
    */
   {
      struct gl_renderbuffer *rb = fb->_ColorDrawBuffer;

      /* color[fragOutput] will be written to buffer */

      if (rb) {
         struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
         GLenum colorType = srb->ColorType;

         assert(colorType == GL_UNSIGNED_BYTE ||
                colorType == GL_FLOAT);

         /* set span->array->rgba to colors for renderbuffer's datatype */
         if (span->array->ChanType != colorType) {
            convert_color_type(span, colorType, 0);
         }
         else {
            if (span->array->ChanType == GL_UNSIGNED_BYTE) {
               span->array->rgba = span->array->rgba8;
            }
            else {
               span->array->rgba = (void *)span->array->attribs[FRAG_ATTRIB_COL];
            }
         }


         ASSERT(rb->_BaseFormat == GL_RGBA ||
                rb->_BaseFormat == GL_RGB ||
                rb->_BaseFormat == GL_RED ||
                rb->_BaseFormat == GL_RG ||
                rb->_BaseFormat == GL_ALPHA);

         if (ctx->Color.ColorLogicOpEnabled) {
            _swrast_logicop_rgba_span(ctx, rb, span);
         }
         else if (ctx->Color.BlendEnabled) {
            _swrast_blend_span(ctx, rb, span);
         }

         if (colorMask != 0xffffffff) {
            _swrast_mask_rgba_span(ctx, rb, span);
         }

         if (span->arrayMask & SPAN_XY) {
            /* array of pixel coords */
            put_values(ctx, rb,
                       span->array->ChanType, span->end,
                       span->array->x, span->array->y,
                       span->array->rgba, span->array->mask);
         }
         else {
            /* horizontal run of pixels */
            _swrast_put_row(ctx, rb,
                            span->array->ChanType,
                            span->end, span->x, span->y,
                            span->array->rgba,
                            span->writeAll ? NULL: span->array->mask);
         }

      } /* if rb */
   }

end:
   /* restore these values before returning */
   span->interpMask = origInterpMask;
   span->arrayMask = origArrayMask;
   span->arrayAttribs = origArrayAttribs;
   span->array->ChanType = origChanType;
   span->array->rgba = origRgba;
}
Beispiel #23
0
/**
 * This is a software fallback for the gl_renderbuffer->AllocStorage
 * function.
 * Device drivers will typically override this function for the buffers
 * which it manages (typically color buffers, Z and stencil).
 * Other buffers (like software accumulation and aux buffers) which the driver
 * doesn't manage can be handled with this function.
 *
 * This one multi-purpose function can allocate stencil, depth, accum, color
 * or color-index buffers!
 */
static GLboolean
soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
                          GLenum internalFormat,
                          GLuint width, GLuint height)
{
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   GLuint bpp;

   switch (internalFormat) {
   case GL_RGB:
   case GL_R3_G3_B2:
   case GL_RGB4:
   case GL_RGB5:
   case GL_RGB8:
   case GL_RGB10:
   case GL_RGB12:
   case GL_RGB16:
      rb->Format = MESA_FORMAT_BGR_UNORM8;
      break;
   case GL_RGBA:
   case GL_RGBA2:
   case GL_RGBA4:
   case GL_RGB5_A1:
   case GL_RGBA8:
#if 1
   case GL_RGB10_A2:
   case GL_RGBA12:
#endif
      if (_mesa_little_endian())
         rb->Format = MESA_FORMAT_R8G8B8A8_UNORM;
      else
         rb->Format = MESA_FORMAT_A8B8G8R8_UNORM;
      break;
   case GL_RGBA16:
   case GL_RGBA16_SNORM:
      /* for accum buffer */
      rb->Format = MESA_FORMAT_RGBA_SNORM16;
      break;
   case GL_STENCIL_INDEX:
   case GL_STENCIL_INDEX1_EXT:
   case GL_STENCIL_INDEX4_EXT:
   case GL_STENCIL_INDEX8_EXT:
   case GL_STENCIL_INDEX16_EXT:
      rb->Format = MESA_FORMAT_S_UINT8;
      break;
   case GL_DEPTH_COMPONENT:
   case GL_DEPTH_COMPONENT16:
      rb->Format = MESA_FORMAT_Z_UNORM16;
      break;
   case GL_DEPTH_COMPONENT24:
      rb->Format = MESA_FORMAT_Z24_UNORM_X8_UINT;
      break;
   case GL_DEPTH_COMPONENT32:
      rb->Format = MESA_FORMAT_Z_UNORM32;
      break;
   case GL_DEPTH_STENCIL_EXT:
   case GL_DEPTH24_STENCIL8_EXT:
      rb->Format = MESA_FORMAT_S8_UINT_Z24_UNORM;
      break;
   default:
      /* unsupported format */
      return GL_FALSE;
   }

   bpp = _mesa_get_format_bytes(rb->Format);

   /* free old buffer storage */
   free(srb->Buffer);
   srb->Buffer = NULL;

   srb->RowStride = width * bpp;

   if (width > 0 && height > 0) {
      /* allocate new buffer storage */
      srb->Buffer = malloc(srb->RowStride * height);

      if (srb->Buffer == NULL) {
         rb->Width = 0;
         rb->Height = 0;
         _mesa_error(ctx, GL_OUT_OF_MEMORY,
                     "software renderbuffer allocation (%d x %d x %d)",
                     width, height, bpp);
         return GL_FALSE;
      }
   }

   rb->Width = width;
   rb->Height = height;
   rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);

   if (rb->Name == 0 &&
       internalFormat == GL_RGBA16_SNORM &&
       rb->_BaseFormat == 0) {
      /* NOTE: This is a special case just for accumulation buffers.
       * This is a very limited use case- there's no snorm texturing or
       * rendering going on.
       */
      rb->_BaseFormat = GL_RGBA;
   }
   else {
      /* the internalFormat should have been error checked long ago */
      assert(rb->_BaseFormat);
   }

   return GL_TRUE;
}