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