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); }
/** * 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); } } } }
/** * 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; } }
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; }
/** * 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]; }
/** * 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]); } } } }
/** * 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); }
/** * 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; } }
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; } }
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); }
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; }
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; }
/** * 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; } }
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; }
/** * 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; } }
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; } }
/* 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; }
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; }
/** * 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; }
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); } }
/** * 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()"); } } }
/** * 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; }
/** * 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; }