1 /**************************************************************************
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
29 #include "main/imports.h"
30 #include "main/macros.h"
31 #include "main/mfeatures.h"
32 #include "main/mtypes.h"
33 #include "main/fbobject.h"
34 #include "main/framebuffer.h"
35 #include "main/renderbuffer.h"
36 #include "main/context.h"
37 #include "main/teximage.h"
38 #include "swrast/swrast.h"
39 #include "drivers/common/meta.h"
41 #include "intel_context.h"
42 #include "intel_batchbuffer.h"
43 #include "intel_buffers.h"
44 #include "intel_fbo.h"
45 #include "intel_mipmap_tree.h"
46 #include "intel_regions.h"
47 #include "intel_tex.h"
48 #include "intel_span.h"
50 #include "brw_context.h"
53 #define FILE_DEBUG_FLAG DEBUG_FBO
57 * Create a new framebuffer object.
59 static struct gl_framebuffer *
60 intel_new_framebuffer(struct gl_context * ctx, GLuint name)
62 /* Only drawable state in intel_framebuffer at this time, just use Mesa's
65 return _mesa_new_framebuffer(ctx, name);
69 /** Called by gl_renderbuffer::Delete() */
71 intel_delete_renderbuffer(struct gl_renderbuffer *rb)
73 GET_CURRENT_CONTEXT(ctx);
74 struct intel_context *intel = intel_context(ctx);
75 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
79 if (intel && irb->region) {
80 intel_region_release(&irb->region);
82 if (intel && irb->hiz_region) {
83 intel_region_release(&irb->hiz_region);
85 if (intel && irb->wrapped_depth) {
86 _mesa_reference_renderbuffer(&irb->wrapped_depth, NULL);
88 if (intel && irb->wrapped_stencil) {
89 _mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL);
97 * Return a pointer to a specific pixel in a renderbuffer.
100 intel_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
103 /* By returning NULL we force all software rendering to go through
111 * Called via glRenderbufferStorageEXT() to set the format and allocate
112 * storage for a user-created renderbuffer.
115 intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
116 GLenum internalFormat,
117 GLuint width, GLuint height)
119 struct intel_context *intel = intel_context(ctx);
120 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
123 ASSERT(rb->Name != 0);
125 switch (internalFormat) {
127 /* Use the same format-choice logic as for textures.
128 * Renderbuffers aren't any different from textures for us,
129 * except they're less useful because you can't texture with
132 rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat,
135 case GL_STENCIL_INDEX:
136 case GL_STENCIL_INDEX1_EXT:
137 case GL_STENCIL_INDEX4_EXT:
138 case GL_STENCIL_INDEX8_EXT:
139 case GL_STENCIL_INDEX16_EXT:
140 /* These aren't actual texture formats, so force them here. */
141 if (intel->has_separate_stencil) {
142 rb->Format = MESA_FORMAT_S8;
144 assert(!intel->must_use_separate_stencil);
145 rb->Format = MESA_FORMAT_S8_Z24;
152 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
153 rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
154 cpp = _mesa_get_format_bytes(rb->Format);
158 /* free old region */
160 intel_region_release(&irb->region);
162 if (irb->hiz_region) {
163 intel_region_release(&irb->hiz_region);
166 /* allocate new memory region/renderbuffer */
168 /* alloc hardware renderbuffer */
169 DBG("Allocating %d x %d Intel RBO\n", width, height);
171 tiling = I915_TILING_NONE;
172 if (intel->use_texture_tiling) {
173 GLenum base_format = _mesa_get_format_base_format(rb->Format);
175 if (intel->gen >= 4 && (base_format == GL_DEPTH_COMPONENT ||
176 base_format == GL_STENCIL_INDEX ||
177 base_format == GL_DEPTH_STENCIL))
178 tiling = I915_TILING_Y;
180 tiling = I915_TILING_X;
183 if (irb->Base.Format == MESA_FORMAT_S8) {
185 * The stencil buffer has quirky pitch requirements. From Vol 2a,
186 * 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
187 * The pitch must be set to 2x the value computed based on width, as
188 * the stencil buffer is stored with two rows interleaved.
189 * To accomplish this, we resort to the nasty hack of doubling the drm
190 * region's cpp and halving its height.
192 * If we neglect to double the pitch, then drm_intel_gem_bo_map_gtt()
193 * maps the memory incorrectly.
195 irb->region = intel_region_alloc(intel->intelScreen,
204 } else if (irb->Base.Format == MESA_FORMAT_S8_Z24
205 && intel->must_use_separate_stencil) {
208 struct gl_renderbuffer *depth_rb;
209 struct gl_renderbuffer *stencil_rb;
211 depth_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
213 stencil_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
215 ok = depth_rb && stencil_rb;
216 ok = ok && intel_alloc_renderbuffer_storage(ctx, depth_rb,
217 depth_rb->InternalFormat,
219 ok = ok && intel_alloc_renderbuffer_storage(ctx, stencil_rb,
220 stencil_rb->InternalFormat,
225 intel_delete_renderbuffer(depth_rb);
228 intel_delete_renderbuffer(stencil_rb);
233 depth_rb->Wrapped = rb;
234 stencil_rb->Wrapped = rb;
235 _mesa_reference_renderbuffer(&irb->wrapped_depth, depth_rb);
236 _mesa_reference_renderbuffer(&irb->wrapped_stencil, stencil_rb);
239 irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp,
240 width, height, GL_TRUE);
244 if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
245 irb->hiz_region = intel_region_alloc(intel->intelScreen,
251 if (!irb->hiz_region) {
252 intel_region_release(&irb->region);
262 #if FEATURE_OES_EGL_image
264 intel_image_target_renderbuffer_storage(struct gl_context *ctx,
265 struct gl_renderbuffer *rb,
268 struct intel_context *intel = intel_context(ctx);
269 struct intel_renderbuffer *irb;
273 screen = intel->intelScreen->driScrnPriv;
274 image = screen->dri2.image->lookupEGLImage(screen, image_handle,
275 screen->loaderPrivate);
279 irb = intel_renderbuffer(rb);
281 intel_region_release(&irb->region);
282 intel_region_reference(&irb->region, image->region);
284 rb->InternalFormat = image->internal_format;
285 rb->Width = image->region->width;
286 rb->Height = image->region->height;
287 rb->Format = image->format;
288 rb->DataType = image->data_type;
289 rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
290 image->internal_format);
295 * Called for each hardware renderbuffer when a _window_ is resized.
296 * Just update fields.
297 * Not used for user-created renderbuffers!
300 intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
301 GLenum internalFormat, GLuint width, GLuint height)
303 ASSERT(rb->Name == 0);
306 rb->InternalFormat = internalFormat;
313 intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
314 GLuint width, GLuint height)
318 _mesa_resize_framebuffer(ctx, fb, width, height);
320 fb->Initialized = GL_TRUE; /* XXX remove someday */
327 /* Make sure all window system renderbuffers are up to date */
328 for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) {
329 struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
331 /* only resize if size is changing */
332 if (rb && (rb->Width != width || rb->Height != height)) {
333 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
339 /** Dummy function for gl_renderbuffer::AllocStorage() */
341 intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
342 GLenum internalFormat, GLuint width, GLuint height)
344 _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
350 intel_renderbuffer_set_region(struct intel_context *intel,
351 struct intel_renderbuffer *rb,
352 struct intel_region *region)
354 struct intel_region *old;
358 intel_region_reference(&rb->region, region);
359 intel_region_release(&old);
364 intel_renderbuffer_set_hiz_region(struct intel_context *intel,
365 struct intel_renderbuffer *rb,
366 struct intel_region *region)
368 struct intel_region *old = rb->hiz_region;
369 rb->hiz_region = NULL;
370 intel_region_reference(&rb->hiz_region, region);
371 intel_region_release(&old);
376 * Create a new intel_renderbuffer which corresponds to an on-screen window,
377 * not a user-created renderbuffer.
379 struct intel_renderbuffer *
380 intel_create_renderbuffer(gl_format format)
382 GET_CURRENT_CONTEXT(ctx);
384 struct intel_renderbuffer *irb;
386 irb = CALLOC_STRUCT(intel_renderbuffer);
388 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
392 _mesa_init_renderbuffer(&irb->Base, 0);
393 irb->Base.ClassID = INTEL_RB_CLASS;
394 irb->Base._BaseFormat = _mesa_get_format_base_format(format);
395 irb->Base.Format = format;
396 irb->Base.InternalFormat = irb->Base._BaseFormat;
397 irb->Base.DataType = intel_mesa_format_to_rb_datatype(format);
399 /* intel-specific methods */
400 irb->Base.Delete = intel_delete_renderbuffer;
401 irb->Base.AllocStorage = intel_alloc_window_storage;
402 irb->Base.GetPointer = intel_get_pointer;
408 struct gl_renderbuffer*
409 intel_create_wrapped_renderbuffer(struct gl_context * ctx,
410 int width, int height,
414 * The name here is irrelevant, as long as its nonzero, because the
415 * renderbuffer never gets entered into Mesa's renderbuffer hash table.
419 struct intel_renderbuffer *irb = CALLOC_STRUCT(intel_renderbuffer);
421 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
425 struct gl_renderbuffer *rb = &irb->Base;
426 _mesa_init_renderbuffer(rb, name);
427 rb->ClassID = INTEL_RB_CLASS;
428 rb->_BaseFormat = _mesa_get_format_base_format(format);
430 rb->InternalFormat = rb->_BaseFormat;
431 rb->DataType = intel_mesa_format_to_rb_datatype(format);
440 * Create a new renderbuffer object.
441 * Typically called via glBindRenderbufferEXT().
443 static struct gl_renderbuffer *
444 intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
446 /*struct intel_context *intel = intel_context(ctx); */
447 struct intel_renderbuffer *irb;
449 irb = CALLOC_STRUCT(intel_renderbuffer);
451 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
455 _mesa_init_renderbuffer(&irb->Base, name);
456 irb->Base.ClassID = INTEL_RB_CLASS;
458 /* intel-specific methods */
459 irb->Base.Delete = intel_delete_renderbuffer;
460 irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
461 irb->Base.GetPointer = intel_get_pointer;
462 /* span routines set in alloc_storage function */
469 * Called via glBindFramebufferEXT().
472 intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
473 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
475 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
476 intel_draw_buffer(ctx, fb);
479 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
485 * Called via glFramebufferRenderbufferEXT().
488 intel_framebuffer_renderbuffer(struct gl_context * ctx,
489 struct gl_framebuffer *fb,
490 GLenum attachment, struct gl_renderbuffer *rb)
492 DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
496 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
497 intel_draw_buffer(ctx, fb);
501 intel_update_tex_wrapper_regions(struct intel_context *intel,
502 struct intel_renderbuffer *irb,
503 struct intel_texture_image *intel_image);
506 intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb,
507 struct gl_texture_image *texImage)
509 struct intel_context *intel = intel_context(ctx);
510 struct intel_texture_image *intel_image = intel_texture_image(texImage);
512 if (!intel_span_supports_format(texImage->TexFormat)) {
513 DBG("Render to texture BAD FORMAT %s\n",
514 _mesa_get_format_name(texImage->TexFormat));
517 DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat));
520 irb->Base.Format = texImage->TexFormat;
521 irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat);
522 irb->Base.InternalFormat = texImage->InternalFormat;
523 irb->Base._BaseFormat = _mesa_base_tex_format(ctx, irb->Base.InternalFormat);
524 irb->Base.Width = texImage->Width;
525 irb->Base.Height = texImage->Height;
527 irb->Base.Delete = intel_delete_renderbuffer;
528 irb->Base.AllocStorage = intel_nop_alloc_storage;
530 if (intel_image->stencil_rb) {
531 /* The tex image has packed depth/stencil format, but is using separate
535 struct intel_renderbuffer *depth_irb =
536 intel_renderbuffer(intel_image->depth_rb);
538 /* Update the hiz region if necessary. */
539 ok = intel_update_tex_wrapper_regions(intel, depth_irb, intel_image);
544 /* The tex image shares its embedded depth and stencil renderbuffers with
545 * the renderbuffer wrapper. */
546 if (irb->wrapped_depth != intel_image->depth_rb) {
547 _mesa_reference_renderbuffer(&irb->wrapped_depth,
548 intel_image->depth_rb);
550 if (irb->wrapped_stencil != intel_image->stencil_rb) {
551 _mesa_reference_renderbuffer(&irb->wrapped_stencil,
552 intel_image->stencil_rb);
558 return intel_update_tex_wrapper_regions(intel, irb, intel_image);
563 * FIXME: The handling of the hiz region is broken for mipmapped depth textures
564 * FIXME: because intel_finalize_mipmap_tree is unaware of it.
567 intel_update_tex_wrapper_regions(struct intel_context *intel,
568 struct intel_renderbuffer *irb,
569 struct intel_texture_image *intel_image)
571 struct gl_renderbuffer *rb = &irb->Base;
573 /* Point the renderbuffer's region to the texture's region. */
574 if (irb->region != intel_image->mt->region) {
575 intel_region_release(&irb->region);
576 intel_region_reference(&irb->region, intel_image->mt->region);
579 /* Allocate the texture's hiz region if necessary. */
580 if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)
581 && !intel_image->mt->hiz_region) {
582 intel_image->mt->hiz_region =
583 intel_region_alloc(intel->intelScreen,
585 _mesa_get_format_bytes(rb->Format),
589 if (!intel_image->mt->hiz_region)
593 /* Point the renderbuffer's hiz region to the texture's hiz region. */
594 if (irb->hiz_region != intel_image->mt->hiz_region) {
595 intel_region_release(&irb->hiz_region);
596 intel_region_reference(&irb->hiz_region, intel_image->mt->hiz_region);
604 * When glFramebufferTexture[123]D is called this function sets up the
605 * gl_renderbuffer wrapper around the texture image.
606 * This will have the region info needed for hardware rendering.
608 static struct intel_renderbuffer *
609 intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
611 const GLuint name = ~0; /* not significant, but distinct for debugging */
612 struct intel_renderbuffer *irb;
614 /* make an intel_renderbuffer to wrap the texture image */
615 irb = CALLOC_STRUCT(intel_renderbuffer);
617 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
621 _mesa_init_renderbuffer(&irb->Base, name);
622 irb->Base.ClassID = INTEL_RB_CLASS;
624 if (!intel_update_wrapper(ctx, irb, texImage)) {
633 intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb,
634 struct intel_texture_image *intel_image,
637 struct intel_mipmap_tree *mt = intel_image->mt;
638 unsigned int dst_x, dst_y;
640 /* compute offset of the particular 2D image within the texture region */
641 intel_miptree_get_image_offset(intel_image->mt,
647 irb->draw_offset = (dst_y * mt->region->pitch + dst_x) * mt->cpp;
653 * Rendering to tiled buffers requires that the base address of the
654 * buffer be aligned to a page boundary. We generally render to
655 * textures by pointing the surface at the mipmap image level, which
656 * may not be aligned to a tile boundary.
658 * This function returns an appropriately-aligned base offset
659 * according to the tiling restrictions, plus any required x/y offset
663 intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
667 int cpp = irb->region->cpp;
668 uint32_t pitch = irb->region->pitch * cpp;
670 if (irb->region->tiling == I915_TILING_NONE) {
673 return irb->draw_x * cpp + irb->draw_y * pitch;
674 } else if (irb->region->tiling == I915_TILING_X) {
675 *tile_x = irb->draw_x % (512 / cpp);
676 *tile_y = irb->draw_y % 8;
677 return ((irb->draw_y / 8) * (8 * pitch) +
678 (irb->draw_x - *tile_x) / (512 / cpp) * 4096);
680 assert(irb->region->tiling == I915_TILING_Y);
681 *tile_x = irb->draw_x % (128 / cpp);
682 *tile_y = irb->draw_y % 32;
683 return ((irb->draw_y / 32) * (32 * pitch) +
684 (irb->draw_x - *tile_x) / (128 / cpp) * 4096);
689 * Called by glFramebufferTexture[123]DEXT() (and other places) to
690 * prepare for rendering into texture memory. This might be called
691 * many times to choose different texture levels, cube faces, etc
692 * before intel_finish_render_texture() is ever called.
695 intel_render_texture(struct gl_context * ctx,
696 struct gl_framebuffer *fb,
697 struct gl_renderbuffer_attachment *att)
699 struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
700 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
701 struct intel_texture_image *intel_image = intel_texture_image(image);
705 if (!intel_image->mt) {
706 /* Fallback on drawing to a texture that doesn't have a miptree
707 * (has a border, width/height 0, etc.)
709 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
710 _swrast_render_texture(ctx, fb, att);
714 irb = intel_wrap_texture(ctx, image);
716 /* bind the wrapper to the attachment point */
717 _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
720 /* fallback to software rendering */
721 _swrast_render_texture(ctx, fb, att);
726 if (!intel_update_wrapper(ctx, irb, image)) {
727 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
728 _swrast_render_texture(ctx, fb, att);
732 DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
734 att->Texture->Name, image->Width, image->Height,
737 intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
738 intel_image->used_as_render_target = GL_TRUE;
741 if (!brw_context(ctx)->has_surface_tile_offset &&
742 (irb->draw_offset & 4095) != 0) {
743 /* Original gen4 hardware couldn't draw to a non-tile-aligned
744 * destination in a miptree unless you actually setup your
745 * renderbuffer as a miptree and used the fragile
746 * lod/array_index/etc. controls to select the image. So,
747 * instead, we just make a new single-level miptree and render
750 struct intel_context *intel = intel_context(ctx);
751 struct intel_mipmap_tree *old_mt = intel_image->mt;
752 struct intel_mipmap_tree *new_mt;
754 new_mt = intel_miptree_create(intel, image->TexObject->Target,
755 intel_image->base.TexFormat,
758 intel_image->base.Width,
759 intel_image->base.Height,
760 intel_image->base.Depth,
763 intel_miptree_image_copy(intel,
769 intel_miptree_release(intel, &intel_image->mt);
770 intel_image->mt = new_mt;
771 intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
773 intel_region_release(&irb->region);
774 intel_region_reference(&irb->region, intel_image->mt->region);
777 /* update drawing region, etc */
778 intel_draw_buffer(ctx, fb);
783 * Called by Mesa when rendering to a texture is done.
786 intel_finish_render_texture(struct gl_context * ctx,
787 struct gl_renderbuffer_attachment *att)
789 struct intel_context *intel = intel_context(ctx);
790 struct gl_texture_object *tex_obj = att->Texture;
791 struct gl_texture_image *image =
792 tex_obj->Image[att->CubeMapFace][att->TextureLevel];
793 struct intel_texture_image *intel_image = intel_texture_image(image);
795 DBG("Finish render texture tid %lx tex=%u\n",
796 _glthread_GetID(), att->Texture->Name);
798 /* Flag that this image may now be validated into the object's miptree. */
800 intel_image->used_as_render_target = GL_FALSE;
802 /* Since we've (probably) rendered to the texture and will (likely) use
803 * it in the texture domain later on in this batchbuffer, flush the
804 * batch. Once again, we wish for a domain tracker in libdrm to cover
805 * usage inside of a batchbuffer like GEM does in the kernel.
807 intel_batchbuffer_emit_mi_flush(intel);
811 * Do additional "completeness" testing of a framebuffer object.
814 intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
816 struct intel_context *intel = intel_context(ctx);
817 const struct intel_renderbuffer *depthRb =
818 intel_get_renderbuffer(fb, BUFFER_DEPTH);
819 const struct intel_renderbuffer *stencilRb =
820 intel_get_renderbuffer(fb, BUFFER_STENCIL);
824 * The depth and stencil renderbuffers are the same renderbuffer or wrap
827 bool depth_stencil_are_same;
828 if (depthRb && stencilRb && depthRb == stencilRb)
829 depth_stencil_are_same = true;
830 else if (depthRb && stencilRb && depthRb != stencilRb
831 && (fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE)
832 && (fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE)
833 && (fb->Attachment[BUFFER_DEPTH].Texture->Name
834 == fb->Attachment[BUFFER_STENCIL].Texture->Name))
835 depth_stencil_are_same = true;
837 depth_stencil_are_same = false;
839 bool fb_has_combined_depth_stencil_format =
840 (depthRb && depthRb->Base.Format == MESA_FORMAT_S8_Z24) ||
841 (stencilRb && stencilRb->Base.Format == MESA_FORMAT_S8_Z24);
843 bool fb_has_hiz = intel_framebuffer_has_hiz(fb);
845 if ((intel->must_use_separate_stencil || fb_has_hiz)
846 && (depth_stencil_are_same || fb_has_combined_depth_stencil_format)) {
847 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
848 } else if (!intel->has_separate_stencil && depthRb && stencilRb && !depth_stencil_are_same) {
849 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
852 for (i = 0; i < Elements(fb->Attachment); i++) {
853 struct gl_renderbuffer *rb;
854 struct intel_renderbuffer *irb;
856 if (fb->Attachment[i].Type == GL_NONE)
859 /* A supported attachment will have a Renderbuffer set either
860 * from being a Renderbuffer or being a texture that got the
861 * intel_wrap_texture() treatment.
863 rb = fb->Attachment[i].Renderbuffer;
865 DBG("attachment without renderbuffer\n");
866 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
870 irb = intel_renderbuffer(rb);
872 DBG("software rendering renderbuffer\n");
873 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
877 if (!intel_span_supports_format(irb->Base.Format) ||
878 !intel->vtbl.render_target_supported(irb->Base.Format)) {
879 DBG("Unsupported texture/renderbuffer format attached: %s\n",
880 _mesa_get_format_name(irb->Base.Format));
881 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
887 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
888 * We can do this when the dst renderbuffer is actually a texture and
889 * there is no scaling, mirroring or scissoring.
891 * \return new buffer mask indicating the buffers left to blit using the
895 intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
896 GLint srcX0, GLint srcY0,
897 GLint srcX1, GLint srcY1,
898 GLint dstX0, GLint dstY0,
899 GLint dstX1, GLint dstY1,
900 GLbitfield mask, GLenum filter)
902 if (mask & GL_COLOR_BUFFER_BIT) {
903 const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
904 const struct gl_framebuffer *readFb = ctx->ReadBuffer;
905 const struct gl_renderbuffer_attachment *drawAtt =
906 &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
908 /* If the source and destination are the same size with no
909 mirroring, the rectangles are within the size of the
910 texture and there is no scissor then we can use
911 glCopyTexSubimage2D to implement the blit. This will end
912 up as a fast hardware blit on some drivers */
913 if (drawAtt && drawAtt->Texture &&
914 srcX0 - srcX1 == dstX0 - dstX1 &&
915 srcY0 - srcY1 == dstY0 - dstY1 &&
918 srcX0 >= 0 && srcX1 <= readFb->Width &&
919 srcY0 >= 0 && srcY1 <= readFb->Height &&
920 dstX0 >= 0 && dstX1 <= drawFb->Width &&
921 dstY0 >= 0 && dstY1 <= drawFb->Height &&
922 !ctx->Scissor.Enabled) {
923 const struct gl_texture_object *texObj = drawAtt->Texture;
924 const GLuint dstLevel = drawAtt->TextureLevel;
925 const GLenum target = texObj->Target;
927 struct gl_texture_image *texImage =
928 _mesa_select_tex_image(ctx, texObj, target, dstLevel);
929 GLenum internalFormat = texImage->InternalFormat;
931 if (intel_copy_texsubimage(intel_context(ctx), target,
932 intel_texture_image(texImage),
936 srcX1 - srcX0, /* width */
938 mask &= ~GL_COLOR_BUFFER_BIT;
946 intel_blit_framebuffer(struct gl_context *ctx,
947 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
948 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
949 GLbitfield mask, GLenum filter)
951 /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
952 mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
953 srcX0, srcY0, srcX1, srcY1,
954 dstX0, dstY0, dstX1, dstY1,
959 _mesa_meta_BlitFramebuffer(ctx,
960 srcX0, srcY0, srcX1, srcY1,
961 dstX0, dstY0, dstX1, dstY1,
966 * Do one-time context initializations related to GL_EXT_framebuffer_object.
967 * Hook in device driver functions.
970 intel_fbo_init(struct intel_context *intel)
972 intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
973 intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
974 intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
975 intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
976 intel->ctx.Driver.RenderTexture = intel_render_texture;
977 intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
978 intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
979 intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
980 intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
982 #if FEATURE_OES_EGL_image
983 intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
984 intel_image_target_renderbuffer_storage;