X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fswrast%2Fs_clear.c;h=158e5dace16fa28a6c3dde502837ce0ba3e3790f;hb=e5339fe4a47c242693962c9f90bbab8b74935cba;hp=75805f9605d4088644b069775030a11eccb761a6;hpb=4926c5748028d33da4808f8a5473aa7b2f2bdc62;p=mesa.git diff --git a/src/mesa/swrast/s_clear.c b/src/mesa/swrast/s_clear.c index 75805f9605d..158e5dace16 100644 --- a/src/mesa/swrast/s_clear.c +++ b/src/mesa/swrast/s_clear.c @@ -1,6 +1,5 @@ /* * Mesa 3-D graphics library - * Version: 7.1 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. * @@ -17,139 +16,225 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ #include "main/glheader.h" -#include "main/colormac.h" +#include "main/accum.h" #include "main/condrender.h" +#include "main/format_pack.h" #include "main/macros.h" -#include "main/imports.h" +#include "util/imports.h" #include "main/mtypes.h" -#include "s_accum.h" #include "s_context.h" #include "s_depth.h" -#include "s_masking.h" #include "s_stencil.h" /** - * Clear the color buffer when glColorMask is in effect. + * Convert a boolean color mask to a packed color where each channel of + * the packed value at dst will be 0 or ~0 depending on the colorMask. */ static void -clear_rgba_buffer_with_masking(struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint buf) +_pack_colormask(mesa_format format, const uint8_t colorMask[4], void *dst) { - const GLint x = ctx->DrawBuffer->_Xmin; - const GLint y = ctx->DrawBuffer->_Ymin; - const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; - const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; - SWspan span; - GLint i; - - ASSERT(rb->PutRow); - - /* Initialize color span with clear color */ - /* XXX optimize for clearcolor == black/zero (bzero) */ - INIT_SPAN(span, GL_BITMAP); - span.end = width; - span.arrayMask = SPAN_RGBA; - span.array->ChanType = rb->DataType; - if (span.array->ChanType == GL_UNSIGNED_BYTE) { - GLubyte clearColor[4]; - UNCLAMPED_FLOAT_TO_UBYTE(clearColor[RCOMP], ctx->Color.ClearColor[0]); - UNCLAMPED_FLOAT_TO_UBYTE(clearColor[GCOMP], ctx->Color.ClearColor[1]); - UNCLAMPED_FLOAT_TO_UBYTE(clearColor[BCOMP], ctx->Color.ClearColor[2]); - UNCLAMPED_FLOAT_TO_UBYTE(clearColor[ACOMP], ctx->Color.ClearColor[3]); - for (i = 0; i < width; i++) { - COPY_4UBV(span.array->rgba[i], clearColor); - } - } - else if (span.array->ChanType == GL_UNSIGNED_SHORT) { - GLushort clearColor[4]; - UNCLAMPED_FLOAT_TO_USHORT(clearColor[RCOMP], ctx->Color.ClearColor[0]); - UNCLAMPED_FLOAT_TO_USHORT(clearColor[GCOMP], ctx->Color.ClearColor[1]); - UNCLAMPED_FLOAT_TO_USHORT(clearColor[BCOMP], ctx->Color.ClearColor[2]); - UNCLAMPED_FLOAT_TO_USHORT(clearColor[ACOMP], ctx->Color.ClearColor[3]); - for (i = 0; i < width; i++) { - COPY_4V_CAST(span.array->rgba[i], clearColor, GLchan); - } - } - else { - ASSERT(span.array->ChanType == GL_FLOAT); - for (i = 0; i < width; i++) { - CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][0], ctx->Color.ClearColor[0]); - CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][1], ctx->Color.ClearColor[1]); - CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][2], ctx->Color.ClearColor[2]); - CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][3], ctx->Color.ClearColor[3]); - } - } + float maskColor[4]; + + switch (_mesa_get_format_datatype(format)) { + case GL_UNSIGNED_NORMALIZED: + /* simple: 1.0 will convert to ~0 in the right bit positions */ + maskColor[0] = colorMask[0] ? 1.0f : 0.0f; + maskColor[1] = colorMask[1] ? 1.0f : 0.0f; + maskColor[2] = colorMask[2] ? 1.0f : 0.0f; + maskColor[3] = colorMask[3] ? 1.0f : 0.0f; + _mesa_pack_float_rgba_row(format, 1, + (const float (*)[4]) maskColor, dst); + break; + case GL_SIGNED_NORMALIZED: + case GL_FLOAT: + /* These formats are harder because it's hard to know the floating + * point values that will convert to ~0 for each color channel's bits. + * This solution just generates a non-zero value for each color channel + * then fixes up the non-zero values to be ~0. + * Note: we'll need to add special case code if we ever have to deal + * with formats with unequal color channel sizes, like R11_G11_B10. + * We issue a warning below for channel sizes other than 8,16,32. + */ + { + uint32_t bits = _mesa_get_format_max_bits(format); /* bits per chan */ + uint32_t bytes = _mesa_get_format_bytes(format); + uint32_t i; + + /* this should put non-zero values into the channels of dst */ + maskColor[0] = colorMask[0] ? -1.0f : 0.0f; + maskColor[1] = colorMask[1] ? -1.0f : 0.0f; + maskColor[2] = colorMask[2] ? -1.0f : 0.0f; + maskColor[3] = colorMask[3] ? -1.0f : 0.0f; + _mesa_pack_float_rgba_row(format, 1, + (const float (*)[4]) maskColor, dst); - /* Note that masking will change the color values, but only the - * channels for which the write mask is GL_FALSE. The channels - * which which are write-enabled won't get modified. - */ - for (i = 0; i < height; i++) { - span.x = x; - span.y = y + i; - _swrast_mask_rgba_span(ctx, rb, &span, buf); - /* write masked row */ - rb->PutRow(ctx, rb, width, x, y + i, span.array->rgba, NULL); + /* fix-up the dst channels by converting non-zero values to ~0 */ + if (bits == 8) { + uint8_t *d = (uint8_t *) dst; + for (i = 0; i < bytes; i++) { + d[i] = d[i] ? 0xff : 0x0; + } + } + else if (bits == 16) { + uint16_t *d = (uint16_t *) dst; + for (i = 0; i < bytes / 2; i++) { + d[i] = d[i] ? 0xffff : 0x0; + } + } + else if (bits == 32) { + uint32_t *d = (uint32_t *) dst; + for (i = 0; i < bytes / 4; i++) { + d[i] = d[i] ? 0xffffffffU : 0x0; + } + } + else { + unreachable("unexpected size in _mesa_pack_colormask()"); + } + } + break; + default: + unreachable("unexpected format data type in gen_color_mask()"); } } - /** - * Clear an rgba color buffer without channel masking. + * Clear an rgba color buffer with masking if needed. */ static void -clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint buf) +clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb, + const GLubyte colorMask[4]) { const GLint x = ctx->DrawBuffer->_Xmin; const GLint y = ctx->DrawBuffer->_Ymin; const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; - GLubyte clear8[4]; - GLushort clear16[4]; - GLvoid *clearVal; - GLint i; - - ASSERT(ctx->Color.ColorMask[buf][0] && - ctx->Color.ColorMask[buf][1] && - ctx->Color.ColorMask[buf][2] && - ctx->Color.ColorMask[buf][3]); - - ASSERT(rb->PutMonoRow); - - switch (rb->DataType) { - case GL_UNSIGNED_BYTE: - UNCLAMPED_FLOAT_TO_UBYTE(clear8[0], ctx->Color.ClearColor[0]); - UNCLAMPED_FLOAT_TO_UBYTE(clear8[1], ctx->Color.ClearColor[1]); - UNCLAMPED_FLOAT_TO_UBYTE(clear8[2], ctx->Color.ClearColor[2]); - UNCLAMPED_FLOAT_TO_UBYTE(clear8[3], ctx->Color.ClearColor[3]); - clearVal = clear8; - break; - case GL_UNSIGNED_SHORT: - UNCLAMPED_FLOAT_TO_USHORT(clear16[0], ctx->Color.ClearColor[0]); - UNCLAMPED_FLOAT_TO_USHORT(clear16[1], ctx->Color.ClearColor[1]); - UNCLAMPED_FLOAT_TO_USHORT(clear16[2], ctx->Color.ClearColor[2]); - UNCLAMPED_FLOAT_TO_USHORT(clear16[3], ctx->Color.ClearColor[3]); - clearVal = clear16; - break; - case GL_FLOAT: - clearVal = ctx->Color.ClearColor; - break; - default: - _mesa_problem(ctx, "Bad rb DataType in clear_color_buffer"); - return; + const GLuint pixelSize = _mesa_get_format_bytes(rb->Format); + const GLboolean doMasking = (colorMask[0] == 0 || + colorMask[1] == 0 || + colorMask[2] == 0 || + colorMask[3] == 0); + const GLfloat (*clearColor)[4] = + (const GLfloat (*)[4]) ctx->Color.ClearColor.f; + GLbitfield mapMode = GL_MAP_WRITE_BIT; + GLubyte *map; + GLint rowStride; + GLint i, j; + + if (doMasking) { + /* we'll need to read buffer values too */ + mapMode |= GL_MAP_READ_BIT; + } + + /* map dest buffer */ + ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, + mapMode, &map, &rowStride, + ctx->DrawBuffer->FlipY); + if (!map) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(color)"); + return; } - for (i = 0; i < height; i++) { - rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL); + /* for 1, 2, 4-byte clearing */ +#define SIMPLE_TYPE_CLEAR(TYPE) \ + do { \ + TYPE pixel, pixelMask; \ + _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, &pixel); \ + if (doMasking) { \ + _pack_colormask(rb->Format, colorMask, &pixelMask); \ + pixel &= pixelMask; \ + pixelMask = ~pixelMask; \ + } \ + for (i = 0; i < height; i++) { \ + TYPE *row = (TYPE *) map; \ + if (doMasking) { \ + for (j = 0; j < width; j++) { \ + row[j] = (row[j] & pixelMask) | pixel; \ + } \ + } \ + else { \ + for (j = 0; j < width; j++) { \ + row[j] = pixel; \ + } \ + } \ + map += rowStride; \ + } \ + } while (0) + + + /* for 3, 6, 8, 12, 16-byte clearing */ +#define MULTI_WORD_CLEAR(TYPE, N) \ + do { \ + TYPE pixel[N], pixelMask[N]; \ + GLuint k; \ + _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, pixel); \ + if (doMasking) { \ + _pack_colormask(rb->Format, colorMask, pixelMask); \ + for (k = 0; k < N; k++) { \ + pixel[k] &= pixelMask[k]; \ + pixelMask[k] = ~pixelMask[k]; \ + } \ + } \ + for (i = 0; i < height; i++) { \ + TYPE *row = (TYPE *) map; \ + if (doMasking) { \ + for (j = 0; j < width; j++) { \ + for (k = 0; k < N; k++) { \ + row[j * N + k] = \ + (row[j * N + k] & pixelMask[k]) | pixel[k]; \ + } \ + } \ + } \ + else { \ + for (j = 0; j < width; j++) { \ + for (k = 0; k < N; k++) { \ + row[j * N + k] = pixel[k]; \ + } \ + } \ + } \ + map += rowStride; \ + } \ + } while(0) + + switch (pixelSize) { + case 1: + SIMPLE_TYPE_CLEAR(GLubyte); + break; + case 2: + SIMPLE_TYPE_CLEAR(GLushort); + break; + case 3: + MULTI_WORD_CLEAR(GLubyte, 3); + break; + case 4: + SIMPLE_TYPE_CLEAR(GLuint); + break; + case 6: + MULTI_WORD_CLEAR(GLushort, 3); + break; + case 8: + MULTI_WORD_CLEAR(GLuint, 2); + break; + case 12: + MULTI_WORD_CLEAR(GLuint, 3); + break; + case 16: + MULTI_WORD_CLEAR(GLuint, 4); + break; + default: + _mesa_problem(ctx, "bad pixel size in clear_rgba_buffer()"); } + + /* unmap buffer */ + ctx->Driver.UnmapRenderbuffer(ctx, rb); } @@ -165,15 +250,21 @@ clear_color_buffers(struct gl_context *ctx) for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) { struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf]; - if (ctx->Color.ColorMask[buf][0] == 0 || - ctx->Color.ColorMask[buf][1] == 0 || - ctx->Color.ColorMask[buf][2] == 0 || - ctx->Color.ColorMask[buf][3] == 0) { - clear_rgba_buffer_with_masking(ctx, rb, buf); - } - else { - clear_rgba_buffer(ctx, rb, buf); - } + + /* If this is an ES2 context or GL_ARB_ES2_compatibility is supported, + * the framebuffer can be complete with some attachments be missing. In + * this case the _ColorDrawBuffers pointer will be NULL. + */ + if (rb == NULL) + continue; + + const GLubyte colormask[4] = { + GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xff : 0, + GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xff : 0, + GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xff : 0, + GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xff : 0, + }; + clear_rgba_buffer(ctx, rb, colormask); } } @@ -188,6 +279,8 @@ clear_color_buffers(struct gl_context *ctx) void _swrast_Clear(struct gl_context *ctx, GLbitfield buffers) { + const GLbitfield BUFFER_DS = BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL; + #ifdef DEBUG_FOO { const GLbitfield legalBits = @@ -206,25 +299,36 @@ _swrast_Clear(struct gl_context *ctx, GLbitfield buffers) if (!_mesa_check_conditional_render(ctx)) return; /* don't clear */ - swrast_render_start(ctx); + if (SWRAST_CONTEXT(ctx)->NewState) + _swrast_validate_derived(ctx); - /* do software clearing here */ - if (buffers) { - if ((buffers & BUFFER_BITS_COLOR) - && (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) { - clear_color_buffers(ctx); - } - if (buffers & BUFFER_BIT_DEPTH) { - _swrast_clear_depth_buffer(ctx, ctx->DrawBuffer->_DepthBuffer); - } - if (buffers & BUFFER_BIT_ACCUM) { - _swrast_clear_accum_buffer(ctx, - ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); + if ((buffers & BUFFER_BITS_COLOR) + && (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) { + clear_color_buffers(ctx); + } + + if (buffers & BUFFER_BIT_ACCUM) { + _mesa_clear_accum_buffer(ctx); + } + + if (buffers & BUFFER_DS) { + struct gl_renderbuffer *depthRb = + ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + struct gl_renderbuffer *stencilRb = + ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; + + if ((buffers & BUFFER_DS) == BUFFER_DS && depthRb == stencilRb) { + /* clear depth and stencil together */ + _swrast_clear_depth_stencil_buffer(ctx); } - if (buffers & BUFFER_BIT_STENCIL) { - _swrast_clear_stencil_buffer(ctx, ctx->DrawBuffer->_StencilBuffer); + else { + /* clear depth, stencil separately */ + if (buffers & BUFFER_BIT_DEPTH) { + _swrast_clear_depth_buffer(ctx); + } + if (buffers & BUFFER_BIT_STENCIL) { + _swrast_clear_stencil_buffer(ctx); + } } } - - swrast_render_finish(ctx); }