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/enums.h"
30 #include "main/imports.h"
31 #include "main/macros.h"
32 #include "main/mfeatures.h"
33 #include "main/mtypes.h"
34 #include "main/fbobject.h"
35 #include "main/framebuffer.h"
36 #include "main/renderbuffer.h"
37 #include "main/context.h"
38 #include "main/teximage.h"
39 #include "swrast/swrast.h"
40 #include "drivers/common/meta.h"
42 #include "intel_context.h"
43 #include "intel_batchbuffer.h"
44 #include "intel_buffers.h"
45 #include "intel_fbo.h"
46 #include "intel_mipmap_tree.h"
47 #include "intel_regions.h"
48 #include "intel_tex.h"
49 #include "intel_span.h"
51 #include "brw_context.h"
54 #define FILE_DEBUG_FLAG DEBUG_FBO
58 * Create a new framebuffer object.
60 static struct gl_framebuffer *
61 intel_new_framebuffer(struct gl_context * ctx, GLuint name)
63 /* Only drawable state in intel_framebuffer at this time, just use Mesa's
66 return _mesa_new_framebuffer(ctx, name);
70 /** Called by gl_renderbuffer::Delete() */
72 intel_delete_renderbuffer(struct gl_renderbuffer *rb)
74 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
78 intel_region_release(&irb->region);
79 intel_region_release(&irb->hiz_region);
81 _mesa_reference_renderbuffer(&irb->wrapped_depth, NULL);
82 _mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL);
88 intel_map_renderbuffer(struct gl_context *ctx,
89 struct gl_renderbuffer *rb,
90 GLuint x, GLuint y, GLuint w, GLuint h,
95 struct intel_context *intel = intel_context(ctx);
96 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
100 /* We sometimes get called with this by our intel_span.c usage. */
107 irb->map_mode = mode;
113 stride = irb->region->pitch * irb->region->cpp;
115 if (rb->Format == MESA_FORMAT_S8) {
117 uint8_t *tiled_s8_map, *untiled_s8_map;
119 /* Flip the Y axis for the default framebuffer. */
120 int y_flip = (rb->Name == 0) ? -1 : 1;
121 int y_bias = (rb->Name == 0) ? (2 * irb->region->height - 1) : 0;
123 /* Perform W-tile deswizzling for stencil buffers into a temporary. */
125 irb->map_buffer = malloc(stride * h);
126 untiled_s8_map = irb->map_buffer;
128 tiled_s8_map = intel_region_map(intel, irb->region, mode);
130 for (pix_y = 0; pix_y < h; pix_y++) {
131 for (pix_x = 0; pix_x < w; pix_x++) {
132 GLuint flipped_y = y_flip * (y + pix_y) + y_bias;
133 intptr_t offset = intel_offset_S8(irb->region->pitch,
137 untiled_s8_map[pix_y * stride + pix_x] = tiled_s8_map[offset];
140 *out_map = untiled_s8_map;
141 *out_stride = stride;
143 DBG("%s: rb %d (%s) s8 detiled mapped: (%d, %d) (%dx%d) -> %p/%d\n",
144 __FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format),
145 x, y, w, h, *out_map, *out_stride);
150 map = intel_region_map(intel, irb->region, mode);
151 stride = irb->region->pitch * irb->region->cpp;
154 map += stride * (irb->region->height - 1);
157 map += irb->draw_x * irb->region->cpp;
158 map += (int)irb->draw_y * stride;
161 map += x * irb->region->cpp;
162 map += (int)y * stride;
165 *out_stride = stride;
169 intel_unmap_renderbuffer(struct gl_context *ctx,
170 struct gl_renderbuffer *rb)
172 struct intel_context *intel = intel_context(ctx);
173 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
175 DBG("%s: rb %d (%s)\n", __FUNCTION__,
176 rb->Name, _mesa_get_format_name(rb->Format));
178 if (irb->map_buffer) {
179 if (irb->map_mode & GL_MAP_WRITE_BIT) {
181 uint8_t *tiled_s8_map = irb->map_buffer;
182 uint8_t *untiled_s8_map = irb->region->bo->virtual;
184 /* Flip the Y axis for the default framebuffer. */
185 int y_flip = (rb->Name == 0) ? -1 : 1;
186 int y_bias = (rb->Name == 0) ? (2 * irb->region->height - 1) : 0;
188 /* Perform W-tile swizzling back out of the temporary. */
189 for (pix_y = 0; pix_y < irb->map_h; pix_y++) {
190 for (pix_x = 0; pix_x < irb->map_w; pix_x++) {
191 GLuint flipped_y = y_flip * (pix_y + irb->map_y) + y_bias;
192 intptr_t offset = intel_offset_S8(irb->region->pitch,
196 tiled_s8_map[offset] =
197 untiled_s8_map[pix_y * irb->map_w + pix_x];
202 intel_region_unmap(intel, irb->region);
203 free(irb->map_buffer);
204 irb->map_buffer = NULL;
207 intel_region_unmap(intel, irb->region);
212 * Return a pointer to a specific pixel in a renderbuffer.
215 intel_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
218 /* By returning NULL we force all software rendering to go through
226 * Called via glRenderbufferStorageEXT() to set the format and allocate
227 * storage for a user-created renderbuffer.
230 intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
231 GLenum internalFormat,
232 GLuint width, GLuint height)
234 struct intel_context *intel = intel_context(ctx);
235 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
238 ASSERT(rb->Name != 0);
240 switch (internalFormat) {
242 /* Use the same format-choice logic as for textures.
243 * Renderbuffers aren't any different from textures for us,
244 * except they're less useful because you can't texture with
247 rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat,
250 case GL_STENCIL_INDEX:
251 case GL_STENCIL_INDEX1_EXT:
252 case GL_STENCIL_INDEX4_EXT:
253 case GL_STENCIL_INDEX8_EXT:
254 case GL_STENCIL_INDEX16_EXT:
255 /* These aren't actual texture formats, so force them here. */
256 if (intel->has_separate_stencil) {
257 rb->Format = MESA_FORMAT_S8;
259 assert(!intel->must_use_separate_stencil);
260 rb->Format = MESA_FORMAT_S8_Z24;
267 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
268 rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
269 cpp = _mesa_get_format_bytes(rb->Format);
273 /* free old region */
275 intel_region_release(&irb->region);
277 if (irb->hiz_region) {
278 intel_region_release(&irb->hiz_region);
281 DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__,
282 _mesa_lookup_enum_by_nr(internalFormat),
283 _mesa_get_format_name(rb->Format), width, height);
285 tiling = I915_TILING_NONE;
286 if (intel->use_texture_tiling) {
287 GLenum base_format = _mesa_get_format_base_format(rb->Format);
289 if (intel->gen >= 4 && (base_format == GL_DEPTH_COMPONENT ||
290 base_format == GL_STENCIL_INDEX ||
291 base_format == GL_DEPTH_STENCIL))
292 tiling = I915_TILING_Y;
294 tiling = I915_TILING_X;
297 if (irb->Base.Format == MESA_FORMAT_S8) {
299 * The stencil buffer is W tiled. However, we request from the kernel a
300 * non-tiled buffer because the GTT is incapable of W fencing.
302 * The stencil buffer has quirky pitch requirements. From Vol 2a,
303 * 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
304 * The pitch must be set to 2x the value computed based on width, as
305 * the stencil buffer is stored with two rows interleaved.
306 * To accomplish this, we resort to the nasty hack of doubling the drm
307 * region's cpp and halving its height.
309 * If we neglect to double the pitch, then render corruption occurs.
311 irb->region = intel_region_alloc(intel->intelScreen,
315 ALIGN((height + 1) / 2, 64),
320 } else if (irb->Base.Format == MESA_FORMAT_S8_Z24
321 && intel->must_use_separate_stencil) {
324 struct gl_renderbuffer *depth_rb;
325 struct gl_renderbuffer *stencil_rb;
327 depth_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
329 stencil_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
331 ok = depth_rb && stencil_rb;
332 ok = ok && intel_alloc_renderbuffer_storage(ctx, depth_rb,
333 depth_rb->InternalFormat,
335 ok = ok && intel_alloc_renderbuffer_storage(ctx, stencil_rb,
336 stencil_rb->InternalFormat,
341 intel_delete_renderbuffer(depth_rb);
344 intel_delete_renderbuffer(stencil_rb);
349 depth_rb->Wrapped = rb;
350 stencil_rb->Wrapped = rb;
351 _mesa_reference_renderbuffer(&irb->wrapped_depth, depth_rb);
352 _mesa_reference_renderbuffer(&irb->wrapped_stencil, stencil_rb);
355 irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp,
356 width, height, true);
360 if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
361 irb->hiz_region = intel_region_alloc(intel->intelScreen,
367 if (!irb->hiz_region) {
368 intel_region_release(&irb->region);
378 #if FEATURE_OES_EGL_image
380 intel_image_target_renderbuffer_storage(struct gl_context *ctx,
381 struct gl_renderbuffer *rb,
384 struct intel_context *intel = intel_context(ctx);
385 struct intel_renderbuffer *irb;
389 screen = intel->intelScreen->driScrnPriv;
390 image = screen->dri2.image->lookupEGLImage(screen, image_handle,
391 screen->loaderPrivate);
395 /* __DRIimage is opaque to the core so it has to be checked here */
396 switch (image->format) {
397 case MESA_FORMAT_RGBA8888_REV:
398 _mesa_error(&intel->ctx, GL_INVALID_OPERATION,
399 "glEGLImageTargetRenderbufferStorage(unsupported image format");
406 irb = intel_renderbuffer(rb);
407 intel_region_reference(&irb->region, image->region);
409 rb->InternalFormat = image->internal_format;
410 rb->Width = image->region->width;
411 rb->Height = image->region->height;
412 rb->Format = image->format;
413 rb->DataType = image->data_type;
414 rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
415 image->internal_format);
420 * Called for each hardware renderbuffer when a _window_ is resized.
421 * Just update fields.
422 * Not used for user-created renderbuffers!
425 intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
426 GLenum internalFormat, GLuint width, GLuint height)
428 ASSERT(rb->Name == 0);
431 rb->InternalFormat = internalFormat;
438 intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
439 GLuint width, GLuint height)
443 _mesa_resize_framebuffer(ctx, fb, width, height);
445 fb->Initialized = true; /* XXX remove someday */
452 /* Make sure all window system renderbuffers are up to date */
453 for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) {
454 struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
456 /* only resize if size is changing */
457 if (rb && (rb->Width != width || rb->Height != height)) {
458 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
464 /** Dummy function for gl_renderbuffer::AllocStorage() */
466 intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
467 GLenum internalFormat, GLuint width, GLuint height)
469 _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
474 * Create a new intel_renderbuffer which corresponds to an on-screen window,
475 * not a user-created renderbuffer.
477 struct intel_renderbuffer *
478 intel_create_renderbuffer(gl_format format)
480 GET_CURRENT_CONTEXT(ctx);
482 struct intel_renderbuffer *irb;
484 irb = CALLOC_STRUCT(intel_renderbuffer);
486 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
490 _mesa_init_renderbuffer(&irb->Base, 0);
491 irb->Base.ClassID = INTEL_RB_CLASS;
492 irb->Base._BaseFormat = _mesa_get_format_base_format(format);
493 irb->Base.Format = format;
494 irb->Base.InternalFormat = irb->Base._BaseFormat;
495 irb->Base.DataType = intel_mesa_format_to_rb_datatype(format);
497 /* intel-specific methods */
498 irb->Base.Delete = intel_delete_renderbuffer;
499 irb->Base.AllocStorage = intel_alloc_window_storage;
500 irb->Base.GetPointer = intel_get_pointer;
506 struct gl_renderbuffer*
507 intel_create_wrapped_renderbuffer(struct gl_context * ctx,
508 int width, int height,
512 * The name here is irrelevant, as long as its nonzero, because the
513 * renderbuffer never gets entered into Mesa's renderbuffer hash table.
517 struct intel_renderbuffer *irb = CALLOC_STRUCT(intel_renderbuffer);
519 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
523 struct gl_renderbuffer *rb = &irb->Base;
524 _mesa_init_renderbuffer(rb, name);
525 rb->ClassID = INTEL_RB_CLASS;
526 rb->_BaseFormat = _mesa_get_format_base_format(format);
528 rb->InternalFormat = rb->_BaseFormat;
529 rb->DataType = intel_mesa_format_to_rb_datatype(format);
538 * Create a new renderbuffer object.
539 * Typically called via glBindRenderbufferEXT().
541 static struct gl_renderbuffer *
542 intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
544 /*struct intel_context *intel = intel_context(ctx); */
545 struct intel_renderbuffer *irb;
547 irb = CALLOC_STRUCT(intel_renderbuffer);
549 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
553 _mesa_init_renderbuffer(&irb->Base, name);
554 irb->Base.ClassID = INTEL_RB_CLASS;
556 /* intel-specific methods */
557 irb->Base.Delete = intel_delete_renderbuffer;
558 irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
559 irb->Base.GetPointer = intel_get_pointer;
560 /* span routines set in alloc_storage function */
567 * Called via glBindFramebufferEXT().
570 intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
571 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
573 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
574 intel_draw_buffer(ctx);
577 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
583 * Called via glFramebufferRenderbufferEXT().
586 intel_framebuffer_renderbuffer(struct gl_context * ctx,
587 struct gl_framebuffer *fb,
588 GLenum attachment, struct gl_renderbuffer *rb)
590 DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
594 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
595 intel_draw_buffer(ctx);
599 intel_update_tex_wrapper_regions(struct intel_context *intel,
600 struct intel_renderbuffer *irb,
601 struct intel_texture_image *intel_image);
604 intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb,
605 struct gl_texture_image *texImage)
607 struct intel_context *intel = intel_context(ctx);
608 struct intel_texture_image *intel_image = intel_texture_image(texImage);
609 int width, height, depth;
611 if (!intel_span_supports_format(texImage->TexFormat)) {
612 DBG("Render to texture BAD FORMAT %s\n",
613 _mesa_get_format_name(texImage->TexFormat));
616 DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat));
619 intel_miptree_get_dimensions_for_image(texImage, &width, &height, &depth);
621 irb->Base.Format = texImage->TexFormat;
622 irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat);
623 irb->Base.InternalFormat = texImage->InternalFormat;
624 irb->Base._BaseFormat = _mesa_base_tex_format(ctx, irb->Base.InternalFormat);
625 irb->Base.Width = width;
626 irb->Base.Height = height;
628 irb->Base.Delete = intel_delete_renderbuffer;
629 irb->Base.AllocStorage = intel_nop_alloc_storage;
631 if (intel_image->stencil_rb) {
632 /* The tex image has packed depth/stencil format, but is using separate
636 struct intel_renderbuffer *depth_irb =
637 intel_renderbuffer(intel_image->depth_rb);
639 /* Update the hiz region if necessary. */
640 ok = intel_update_tex_wrapper_regions(intel, depth_irb, intel_image);
645 /* The tex image shares its embedded depth and stencil renderbuffers with
646 * the renderbuffer wrapper. */
647 _mesa_reference_renderbuffer(&irb->wrapped_depth,
648 intel_image->depth_rb);
649 _mesa_reference_renderbuffer(&irb->wrapped_stencil,
650 intel_image->stencil_rb);
654 return intel_update_tex_wrapper_regions(intel, irb, intel_image);
659 * FIXME: The handling of the hiz region is broken for mipmapped depth textures
660 * FIXME: because intel_finalize_mipmap_tree is unaware of it.
663 intel_update_tex_wrapper_regions(struct intel_context *intel,
664 struct intel_renderbuffer *irb,
665 struct intel_texture_image *intel_image)
667 struct gl_renderbuffer *rb = &irb->Base;
669 /* Point the renderbuffer's region to the texture's region. */
670 if (irb->region != intel_image->mt->region) {
671 intel_region_reference(&irb->region, intel_image->mt->region);
674 /* Allocate the texture's hiz region if necessary. */
675 if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)
676 && !intel_image->mt->hiz_region) {
677 intel_image->mt->hiz_region =
678 intel_region_alloc(intel->intelScreen,
680 _mesa_get_format_bytes(rb->Format),
684 if (!intel_image->mt->hiz_region)
688 /* Point the renderbuffer's hiz region to the texture's hiz region. */
689 if (irb->hiz_region != intel_image->mt->hiz_region) {
690 intel_region_reference(&irb->hiz_region, intel_image->mt->hiz_region);
698 * When glFramebufferTexture[123]D is called this function sets up the
699 * gl_renderbuffer wrapper around the texture image.
700 * This will have the region info needed for hardware rendering.
702 static struct intel_renderbuffer *
703 intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
705 const GLuint name = ~0; /* not significant, but distinct for debugging */
706 struct intel_renderbuffer *irb;
708 /* make an intel_renderbuffer to wrap the texture image */
709 irb = CALLOC_STRUCT(intel_renderbuffer);
711 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
715 _mesa_init_renderbuffer(&irb->Base, name);
716 irb->Base.ClassID = INTEL_RB_CLASS;
718 if (!intel_update_wrapper(ctx, irb, texImage)) {
727 intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb,
728 struct intel_texture_image *intel_image,
731 unsigned int dst_x, dst_y;
733 /* compute offset of the particular 2D image within the texture region */
734 intel_miptree_get_image_offset(intel_image->mt,
735 intel_image->base.Base.Level,
736 intel_image->base.Base.Face,
745 * Rendering to tiled buffers requires that the base address of the
746 * buffer be aligned to a page boundary. We generally render to
747 * textures by pointing the surface at the mipmap image level, which
748 * may not be aligned to a tile boundary.
750 * This function returns an appropriately-aligned base offset
751 * according to the tiling restrictions, plus any required x/y offset
755 intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
759 int cpp = irb->region->cpp;
760 uint32_t pitch = irb->region->pitch * cpp;
762 if (irb->region->tiling == I915_TILING_NONE) {
765 return irb->draw_x * cpp + irb->draw_y * pitch;
766 } else if (irb->region->tiling == I915_TILING_X) {
767 *tile_x = irb->draw_x % (512 / cpp);
768 *tile_y = irb->draw_y % 8;
769 return ((irb->draw_y / 8) * (8 * pitch) +
770 (irb->draw_x - *tile_x) / (512 / cpp) * 4096);
772 assert(irb->region->tiling == I915_TILING_Y);
773 *tile_x = irb->draw_x % (128 / cpp);
774 *tile_y = irb->draw_y % 32;
775 return ((irb->draw_y / 32) * (32 * pitch) +
776 (irb->draw_x - *tile_x) / (128 / cpp) * 4096);
782 need_tile_offset_workaround(struct brw_context *brw,
783 struct intel_renderbuffer *irb)
785 uint32_t tile_x, tile_y;
787 if (brw->has_surface_tile_offset)
790 intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y);
792 return tile_x != 0 || tile_y != 0;
797 * Called by glFramebufferTexture[123]DEXT() (and other places) to
798 * prepare for rendering into texture memory. This might be called
799 * many times to choose different texture levels, cube faces, etc
800 * before intel_finish_render_texture() is ever called.
803 intel_render_texture(struct gl_context * ctx,
804 struct gl_framebuffer *fb,
805 struct gl_renderbuffer_attachment *att)
807 struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
808 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
809 struct intel_texture_image *intel_image = intel_texture_image(image);
813 if (!intel_image->mt) {
814 /* Fallback on drawing to a texture that doesn't have a miptree
815 * (has a border, width/height 0, etc.)
817 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
818 _swrast_render_texture(ctx, fb, att);
822 irb = intel_wrap_texture(ctx, image);
824 /* bind the wrapper to the attachment point */
825 _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
828 /* fallback to software rendering */
829 _swrast_render_texture(ctx, fb, att);
834 if (!intel_update_wrapper(ctx, irb, image)) {
835 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
836 _swrast_render_texture(ctx, fb, att);
840 DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
842 att->Texture->Name, image->Width, image->Height,
845 intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
846 intel_image->used_as_render_target = true;
849 if (need_tile_offset_workaround(brw_context(ctx), irb)) {
850 /* Original gen4 hardware couldn't draw to a non-tile-aligned
851 * destination in a miptree unless you actually setup your
852 * renderbuffer as a miptree and used the fragile
853 * lod/array_index/etc. controls to select the image. So,
854 * instead, we just make a new single-level miptree and render
857 struct intel_context *intel = intel_context(ctx);
858 struct intel_mipmap_tree *new_mt;
859 int width, height, depth;
861 intel_miptree_get_dimensions_for_image(image, &width, &height, &depth);
863 new_mt = intel_miptree_create(intel, image->TexObject->Target,
864 intel_image->base.Base.TexFormat,
865 intel_image->base.Base.Level,
866 intel_image->base.Base.Level,
867 width, height, depth,
870 intel_miptree_copy_teximage(intel, intel_image, new_mt);
871 intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
873 intel_region_reference(&irb->region, intel_image->mt->region);
874 intel_miptree_release(&new_mt);
877 /* update drawing region, etc */
878 intel_draw_buffer(ctx);
883 * Called by Mesa when rendering to a texture is done.
886 intel_finish_render_texture(struct gl_context * ctx,
887 struct gl_renderbuffer_attachment *att)
889 struct intel_context *intel = intel_context(ctx);
890 struct gl_texture_object *tex_obj = att->Texture;
891 struct gl_texture_image *image =
892 tex_obj->Image[att->CubeMapFace][att->TextureLevel];
893 struct intel_texture_image *intel_image = intel_texture_image(image);
895 DBG("Finish render texture tid %lx tex=%u\n",
896 _glthread_GetID(), att->Texture->Name);
898 /* Flag that this image may now be validated into the object's miptree. */
900 intel_image->used_as_render_target = false;
902 /* Since we've (probably) rendered to the texture and will (likely) use
903 * it in the texture domain later on in this batchbuffer, flush the
904 * batch. Once again, we wish for a domain tracker in libdrm to cover
905 * usage inside of a batchbuffer like GEM does in the kernel.
907 intel_batchbuffer_emit_mi_flush(intel);
911 * Do additional "completeness" testing of a framebuffer object.
914 intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
916 struct intel_context *intel = intel_context(ctx);
917 const struct intel_renderbuffer *depthRb =
918 intel_get_renderbuffer(fb, BUFFER_DEPTH);
919 const struct intel_renderbuffer *stencilRb =
920 intel_get_renderbuffer(fb, BUFFER_STENCIL);
924 * The depth and stencil renderbuffers are the same renderbuffer or wrap
927 if (depthRb && stencilRb) {
928 bool depth_stencil_are_same;
929 if (depthRb == stencilRb)
930 depth_stencil_are_same = true;
931 else if ((fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE) &&
932 (fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE) &&
933 (fb->Attachment[BUFFER_DEPTH].Texture->Name ==
934 fb->Attachment[BUFFER_STENCIL].Texture->Name))
935 depth_stencil_are_same = true;
937 depth_stencil_are_same = false;
939 if (!intel->has_separate_stencil && !depth_stencil_are_same) {
940 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
944 for (i = 0; i < Elements(fb->Attachment); i++) {
945 struct gl_renderbuffer *rb;
946 struct intel_renderbuffer *irb;
948 if (fb->Attachment[i].Type == GL_NONE)
951 /* A supported attachment will have a Renderbuffer set either
952 * from being a Renderbuffer or being a texture that got the
953 * intel_wrap_texture() treatment.
955 rb = fb->Attachment[i].Renderbuffer;
957 DBG("attachment without renderbuffer\n");
958 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
962 irb = intel_renderbuffer(rb);
964 DBG("software rendering renderbuffer\n");
965 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
969 if (!intel_span_supports_format(irb->Base.Format) ||
970 !intel->vtbl.render_target_supported(irb->Base.Format)) {
971 DBG("Unsupported texture/renderbuffer format attached: %s\n",
972 _mesa_get_format_name(irb->Base.Format));
973 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
979 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
980 * We can do this when the dst renderbuffer is actually a texture and
981 * there is no scaling, mirroring or scissoring.
983 * \return new buffer mask indicating the buffers left to blit using the
987 intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
988 GLint srcX0, GLint srcY0,
989 GLint srcX1, GLint srcY1,
990 GLint dstX0, GLint dstY0,
991 GLint dstX1, GLint dstY1,
992 GLbitfield mask, GLenum filter)
994 if (mask & GL_COLOR_BUFFER_BIT) {
995 const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
996 const struct gl_framebuffer *readFb = ctx->ReadBuffer;
997 const struct gl_renderbuffer_attachment *drawAtt =
998 &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
1000 /* If the source and destination are the same size with no
1001 mirroring, the rectangles are within the size of the
1002 texture and there is no scissor then we can use
1003 glCopyTexSubimage2D to implement the blit. This will end
1004 up as a fast hardware blit on some drivers */
1005 if (drawAtt && drawAtt->Texture &&
1006 srcX0 - srcX1 == dstX0 - dstX1 &&
1007 srcY0 - srcY1 == dstY0 - dstY1 &&
1010 srcX0 >= 0 && srcX1 <= readFb->Width &&
1011 srcY0 >= 0 && srcY1 <= readFb->Height &&
1012 dstX0 >= 0 && dstX1 <= drawFb->Width &&
1013 dstY0 >= 0 && dstY1 <= drawFb->Height &&
1014 !ctx->Scissor.Enabled) {
1015 const struct gl_texture_object *texObj = drawAtt->Texture;
1016 const GLuint dstLevel = drawAtt->TextureLevel;
1017 const GLenum target = texObj->Target;
1019 struct gl_texture_image *texImage =
1020 _mesa_select_tex_image(ctx, texObj, target, dstLevel);
1022 if (intel_copy_texsubimage(intel_context(ctx),
1023 intel_texture_image(texImage),
1026 srcX1 - srcX0, /* width */
1028 mask &= ~GL_COLOR_BUFFER_BIT;
1036 intel_blit_framebuffer(struct gl_context *ctx,
1037 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1038 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1039 GLbitfield mask, GLenum filter)
1041 /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
1042 mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
1043 srcX0, srcY0, srcX1, srcY1,
1044 dstX0, dstY0, dstX1, dstY1,
1049 _mesa_meta_BlitFramebuffer(ctx,
1050 srcX0, srcY0, srcX1, srcY1,
1051 dstX0, dstY0, dstX1, dstY1,
1056 * Do one-time context initializations related to GL_EXT_framebuffer_object.
1057 * Hook in device driver functions.
1060 intel_fbo_init(struct intel_context *intel)
1062 intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
1063 intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
1064 intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer;
1065 intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer;
1066 intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
1067 intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
1068 intel->ctx.Driver.RenderTexture = intel_render_texture;
1069 intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
1070 intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
1071 intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
1072 intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
1074 #if FEATURE_OES_EGL_image
1075 intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
1076 intel_image_target_renderbuffer_storage;