Example #1
0
/**
 * Update the framebuffer's _DepthBuffer field using the renderbuffer
 * found at the given attachment index.
 *
 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
 * create and install a depth wrapper/adaptor.
 *
 * \param fb  the framebuffer whose _DepthBuffer field to update
 * \param attIndex  indicates the renderbuffer to possibly wrap
 */
void
_mesa_update_depth_buffer(struct gl_context *ctx,
                          struct gl_framebuffer *fb,
                          GLuint attIndex)
{
   struct gl_renderbuffer *depthRb;

   /* only one possiblity for now */
   ASSERT(attIndex == BUFFER_DEPTH);

   depthRb = fb->Attachment[attIndex].Renderbuffer;

   if (depthRb && _mesa_is_format_packed_depth_stencil(depthRb->Format)) {
      /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */
      if (!fb->_DepthBuffer
          || fb->_DepthBuffer->Wrapped != depthRb
          || _mesa_get_format_base_format(fb->_DepthBuffer->Format) != GL_DEPTH_COMPONENT) {
         /* need to update wrapper */
         struct gl_renderbuffer *wrapper
            = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb);
         _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper);
         ASSERT(fb->_DepthBuffer->Wrapped == depthRb);
      }
   }
   else {
      /* depthRb may be null */
      _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb);
   }
}
Example #2
0
/**
 * Update the framebuffer's _StencilBuffer field using the renderbuffer
 * found at the given attachment index.
 *
 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
 * create and install a stencil wrapper/adaptor.
 *
 * \param fb  the framebuffer whose _StencilBuffer field to update
 * \param attIndex  indicates the renderbuffer to possibly wrap
 */
void
_mesa_update_stencil_buffer(struct gl_context *ctx,
                            struct gl_framebuffer *fb,
                            GLuint attIndex)
{
   struct gl_renderbuffer *stencilRb;

   ASSERT(attIndex == BUFFER_DEPTH ||
          attIndex == BUFFER_STENCIL);

   stencilRb = fb->Attachment[attIndex].Renderbuffer;

   if (stencilRb && _mesa_is_format_packed_depth_stencil(stencilRb->Format)) {
      /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */
      if (!fb->_StencilBuffer
          || fb->_StencilBuffer->Wrapped != stencilRb
          || _mesa_get_format_base_format(fb->_StencilBuffer->Format) != GL_STENCIL_INDEX) {
         /* need to update wrapper */
         struct gl_renderbuffer *wrapper
            = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb);
         _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper);
         ASSERT(fb->_StencilBuffer->Wrapped == stencilRb);
      }
   }
   else {
      /* stencilRb may be null */
      _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb);
   }
}
void
brw_emit_depthbuffer(struct brw_context *brw)
{
   struct intel_context *intel = &brw->intel;
   struct gl_context *ctx = &intel->ctx;
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   /* _NEW_BUFFERS */
   struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
   struct intel_renderbuffer *stencil_irb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
   struct intel_mipmap_tree *depth_mt = brw->depthstencil.depth_mt;
   struct intel_mipmap_tree *stencil_mt = brw->depthstencil.stencil_mt;
   struct intel_mipmap_tree *hiz_mt = brw->depthstencil.hiz_mt;
   uint32_t tile_x = brw->depthstencil.tile_x;
   uint32_t tile_y = brw->depthstencil.tile_y;
   bool separate_stencil = false;
   uint32_t depth_surface_type = BRW_SURFACE_NULL;
   uint32_t depthbuffer_format = BRW_DEPTHFORMAT_D32_FLOAT;
   uint32_t depth_offset = 0;
   uint32_t width = 1, height = 1;

   if (stencil_mt) {
      separate_stencil = stencil_mt->format == MESA_FORMAT_S8;

      /* Gen7 supports only separate stencil */
      assert(separate_stencil || intel->gen < 7);
   }

   /* If there's a packed depth/stencil bound to stencil only, we need to
    * emit the packed depth/stencil buffer packet.
    */
   if (!depth_irb && stencil_irb && !separate_stencil) {
      depth_irb = stencil_irb;
      depth_mt = stencil_mt;
   }

   if (depth_irb && depth_mt) {
      struct intel_region *region = depth_mt->region;

      /* When 3DSTATE_DEPTH_BUFFER.Separate_Stencil_Enable is set, then
       * 3DSTATE_DEPTH_BUFFER.Surface_Format is not permitted to be a packed
       * depthstencil format.
       *
       * Gens prior to 7 require that HiZ_Enable and Separate_Stencil_Enable be
       * set to the same value. Gens after 7 implicitly always set
       * Separate_Stencil_Enable; software cannot disable it.
       */
      if ((intel->gen < 7 && depth_mt->hiz_mt) || intel->gen >= 7) {
         assert(!_mesa_is_format_packed_depth_stencil(depth_mt->format));
      }

      /* Prior to Gen7, if using separate stencil, hiz must be enabled. */
      assert(intel->gen >= 7 || !separate_stencil || hiz_mt);

      assert(intel->gen < 6 || region->tiling == I915_TILING_Y);
      assert(!hiz_mt || region->tiling == I915_TILING_Y);

      depthbuffer_format = brw_depthbuffer_format(brw);
      depth_surface_type = BRW_SURFACE_2D;
      depth_offset = brw->depthstencil.depth_offset;
      width = depth_irb->Base.Base.Width;
      height = depth_irb->Base.Base.Height;
   } else if (separate_stencil) {
      /*
       * There exists a separate stencil buffer but no depth buffer.
       *
       * The stencil buffer inherits most of its fields from
       * 3DSTATE_DEPTH_BUFFER: namely the tile walk, surface type, width, and
       * height.
       *
       * The tiled bit must be set. From the Sandybridge PRM, Volume 2, Part 1,
       * Section 7.5.5.1.1 3DSTATE_DEPTH_BUFFER, Bit 1.27 Tiled Surface:
       *     [DevGT+]: This field must be set to TRUE.
       */
      assert(intel->has_separate_stencil);

      depth_surface_type = BRW_SURFACE_2D;
      width = stencil_irb->Base.Base.Width;
      height = stencil_irb->Base.Base.Height;
   }

   intel->vtbl.emit_depth_stencil_hiz(brw, depth_mt, depth_offset,
                                      depthbuffer_format, depth_surface_type,
                                      stencil_mt, hiz_mt, separate_stencil,
                                      width, height, tile_x, tile_y);
}
Example #4
0
/**
 * Try to do a fast 1:1 blit with memcpy.
 * \return GL_TRUE if successful, GL_FALSE otherwise.
 */
GLboolean
swrast_fast_copy_pixels(struct gl_context *ctx,
                        GLint srcX, GLint srcY, GLsizei width, GLsizei height,
                        GLint dstX, GLint dstY, GLenum type)
{
    struct gl_framebuffer *srcFb = ctx->ReadBuffer;
    struct gl_framebuffer *dstFb = ctx->DrawBuffer;
    struct gl_renderbuffer *srcRb, *dstRb;
    GLint row;
    GLuint pixelBytes, widthInBytes;
    GLubyte *srcMap, *dstMap;
    GLint srcRowStride, dstRowStride;

    if (type == GL_COLOR) {
        if (dstFb->_NumColorDrawBuffers != 1)
            return GL_FALSE;
        srcRb = srcFb->_ColorReadBuffer;
        dstRb = dstFb->_ColorDrawBuffers[0];
    }
    else if (type == GL_STENCIL) {
        srcRb = srcFb->Attachment[BUFFER_STENCIL].Renderbuffer;
        dstRb = dstFb->Attachment[BUFFER_STENCIL].Renderbuffer;
    }
    else if (type == GL_DEPTH) {
        srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
        dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
    }
    else {
        ASSERT(type == GL_DEPTH_STENCIL_EXT);
        /* XXX correct? */
        srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
        dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
    }

    /* src and dst renderbuffers must be same format */
    if (!srcRb || !dstRb || srcRb->Format != dstRb->Format) {
        return GL_FALSE;
    }

    if (type == GL_STENCIL || type == GL_DEPTH_COMPONENT) {
        /* can't handle packed depth+stencil here */
        if (_mesa_is_format_packed_depth_stencil(srcRb->Format) ||
                _mesa_is_format_packed_depth_stencil(dstRb->Format))
            return GL_FALSE;
    }
    else if (type == GL_DEPTH_STENCIL) {
        /* can't handle separate depth/stencil buffers */
        if (srcRb != srcFb->Attachment[BUFFER_STENCIL].Renderbuffer ||
                dstRb != dstFb->Attachment[BUFFER_STENCIL].Renderbuffer)
            return GL_FALSE;
    }

    /* clipping not supported */
    if (srcX < 0 || srcX + width > (GLint) srcFb->Width ||
            srcY < 0 || srcY + height > (GLint) srcFb->Height ||
            dstX < dstFb->_Xmin || dstX + width > dstFb->_Xmax ||
            dstY < dstFb->_Ymin || dstY + height > dstFb->_Ymax) {
        return GL_FALSE;
    }

    pixelBytes = _mesa_get_format_bytes(srcRb->Format);
    widthInBytes = width * pixelBytes;

    if (srcRb == dstRb) {
        /* map whole buffer for read/write */
        /* XXX we could be clever and just map the union region of the
         * source and dest rects.
         */
        GLubyte *map;
        GLint rowStride;

        ctx->Driver.MapRenderbuffer(ctx, srcRb, 0, 0,
                                    srcRb->Width, srcRb->Height,
                                    GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
                                    &map, &rowStride);
        if (!map) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
            return GL_TRUE; /* don't retry with slow path */
        }

        srcMap = map + srcY * rowStride + srcX * pixelBytes;
        dstMap = map + dstY * rowStride + dstX * pixelBytes;

        /* this handles overlapping copies */
        if (srcY < dstY) {
            /* copy in reverse (top->down) order */
            srcMap += rowStride * (height - 1);
            dstMap += rowStride * (height - 1);
            srcRowStride = -rowStride;
            dstRowStride = -rowStride;
        }
        else {
            /* copy in normal (bottom->up) order */
            srcRowStride = rowStride;
            dstRowStride = rowStride;
        }
    }
    else {
        /* different src/dst buffers */
        ctx->Driver.MapRenderbuffer(ctx, srcRb, srcX, srcY,
                                    width, height,
                                    GL_MAP_READ_BIT, &srcMap, &srcRowStride);
        if (!srcMap) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
            return GL_TRUE; /* don't retry with slow path */
        }
        ctx->Driver.MapRenderbuffer(ctx, dstRb, dstX, dstY,
                                    width, height,
                                    GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
        if (!dstMap) {
            ctx->Driver.UnmapRenderbuffer(ctx, srcRb);
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
            return GL_TRUE; /* don't retry with slow path */
        }
    }

    for (row = 0; row < height; row++) {
        /* memmove() in case of overlap */
        memmove(dstMap, srcMap, widthInBytes);
        dstMap += dstRowStride;
        srcMap += srcRowStride;
    }

    ctx->Driver.UnmapRenderbuffer(ctx, srcRb);
    if (dstRb != srcRb) {
        ctx->Driver.UnmapRenderbuffer(ctx, dstRb);
    }

    return GL_TRUE;
}