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 struct intel_renderbuffer
*irb
= intel_renderbuffer(rb
);
77 intel_region_release(&irb
->region
);
78 intel_region_release(&irb
->hiz_region
);
80 _mesa_reference_renderbuffer(&irb
->wrapped_depth
, NULL
);
81 _mesa_reference_renderbuffer(&irb
->wrapped_stencil
, NULL
);
88 * Return a pointer to a specific pixel in a renderbuffer.
91 intel_get_pointer(struct gl_context
* ctx
, struct gl_renderbuffer
*rb
,
94 /* By returning NULL we force all software rendering to go through
102 * Called via glRenderbufferStorageEXT() to set the format and allocate
103 * storage for a user-created renderbuffer.
106 intel_alloc_renderbuffer_storage(struct gl_context
* ctx
, struct gl_renderbuffer
*rb
,
107 GLenum internalFormat
,
108 GLuint width
, GLuint height
)
110 struct intel_context
*intel
= intel_context(ctx
);
111 struct intel_renderbuffer
*irb
= intel_renderbuffer(rb
);
114 ASSERT(rb
->Name
!= 0);
116 switch (internalFormat
) {
118 /* Use the same format-choice logic as for textures.
119 * Renderbuffers aren't any different from textures for us,
120 * except they're less useful because you can't texture with
123 rb
->Format
= intel
->ctx
.Driver
.ChooseTextureFormat(ctx
, internalFormat
,
126 case GL_STENCIL_INDEX
:
127 case GL_STENCIL_INDEX1_EXT
:
128 case GL_STENCIL_INDEX4_EXT
:
129 case GL_STENCIL_INDEX8_EXT
:
130 case GL_STENCIL_INDEX16_EXT
:
131 /* These aren't actual texture formats, so force them here. */
132 if (intel
->has_separate_stencil
) {
133 rb
->Format
= MESA_FORMAT_S8
;
135 assert(!intel
->must_use_separate_stencil
);
136 rb
->Format
= MESA_FORMAT_S8_Z24
;
143 rb
->_BaseFormat
= _mesa_base_fbo_format(ctx
, internalFormat
);
144 rb
->DataType
= intel_mesa_format_to_rb_datatype(rb
->Format
);
145 cpp
= _mesa_get_format_bytes(rb
->Format
);
149 /* free old region */
151 intel_region_release(&irb
->region
);
153 if (irb
->hiz_region
) {
154 intel_region_release(&irb
->hiz_region
);
157 /* allocate new memory region/renderbuffer */
159 /* alloc hardware renderbuffer */
160 DBG("Allocating %d x %d Intel RBO\n", width
, height
);
162 tiling
= I915_TILING_NONE
;
163 if (intel
->use_texture_tiling
) {
164 GLenum base_format
= _mesa_get_format_base_format(rb
->Format
);
166 if (intel
->gen
>= 4 && (base_format
== GL_DEPTH_COMPONENT
||
167 base_format
== GL_STENCIL_INDEX
||
168 base_format
== GL_DEPTH_STENCIL
))
169 tiling
= I915_TILING_Y
;
171 tiling
= I915_TILING_X
;
174 if (irb
->Base
.Format
== MESA_FORMAT_S8
) {
176 * The stencil buffer is W tiled. However, we request from the kernel a
177 * non-tiled buffer because the GTT is incapable of W fencing.
179 * The stencil buffer has quirky pitch requirements. From Vol 2a,
180 * 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
181 * The pitch must be set to 2x the value computed based on width, as
182 * the stencil buffer is stored with two rows interleaved.
183 * To accomplish this, we resort to the nasty hack of doubling the drm
184 * region's cpp and halving its height.
186 * If we neglect to double the pitch, then render corruption occurs.
188 irb
->region
= intel_region_alloc(intel
->intelScreen
,
192 ALIGN((height
+ 1) / 2, 64),
197 } else if (irb
->Base
.Format
== MESA_FORMAT_S8_Z24
198 && intel
->must_use_separate_stencil
) {
201 struct gl_renderbuffer
*depth_rb
;
202 struct gl_renderbuffer
*stencil_rb
;
204 depth_rb
= intel_create_wrapped_renderbuffer(ctx
, width
, height
,
206 stencil_rb
= intel_create_wrapped_renderbuffer(ctx
, width
, height
,
208 ok
= depth_rb
&& stencil_rb
;
209 ok
= ok
&& intel_alloc_renderbuffer_storage(ctx
, depth_rb
,
210 depth_rb
->InternalFormat
,
212 ok
= ok
&& intel_alloc_renderbuffer_storage(ctx
, stencil_rb
,
213 stencil_rb
->InternalFormat
,
218 intel_delete_renderbuffer(depth_rb
);
221 intel_delete_renderbuffer(stencil_rb
);
226 depth_rb
->Wrapped
= rb
;
227 stencil_rb
->Wrapped
= rb
;
228 _mesa_reference_renderbuffer(&irb
->wrapped_depth
, depth_rb
);
229 _mesa_reference_renderbuffer(&irb
->wrapped_stencil
, stencil_rb
);
232 irb
->region
= intel_region_alloc(intel
->intelScreen
, tiling
, cpp
,
233 width
, height
, true);
237 if (intel
->vtbl
.is_hiz_depth_format(intel
, rb
->Format
)) {
238 irb
->hiz_region
= intel_region_alloc(intel
->intelScreen
,
244 if (!irb
->hiz_region
) {
245 intel_region_release(&irb
->region
);
255 #if FEATURE_OES_EGL_image
257 intel_image_target_renderbuffer_storage(struct gl_context
*ctx
,
258 struct gl_renderbuffer
*rb
,
261 struct intel_context
*intel
= intel_context(ctx
);
262 struct intel_renderbuffer
*irb
;
266 screen
= intel
->intelScreen
->driScrnPriv
;
267 image
= screen
->dri2
.image
->lookupEGLImage(screen
, image_handle
,
268 screen
->loaderPrivate
);
272 /* __DRIimage is opaque to the core so it has to be checked here */
273 switch (image
->format
) {
274 case MESA_FORMAT_RGBA8888_REV
:
275 _mesa_error(&intel
->ctx
, GL_INVALID_OPERATION
,
276 "glEGLImageTargetRenderbufferStorage(unsupported image format");
283 irb
= intel_renderbuffer(rb
);
284 intel_region_reference(&irb
->region
, image
->region
);
286 rb
->InternalFormat
= image
->internal_format
;
287 rb
->Width
= image
->region
->width
;
288 rb
->Height
= image
->region
->height
;
289 rb
->Format
= image
->format
;
290 rb
->DataType
= image
->data_type
;
291 rb
->_BaseFormat
= _mesa_base_fbo_format(&intel
->ctx
,
292 image
->internal_format
);
297 * Called for each hardware renderbuffer when a _window_ is resized.
298 * Just update fields.
299 * Not used for user-created renderbuffers!
302 intel_alloc_window_storage(struct gl_context
* ctx
, struct gl_renderbuffer
*rb
,
303 GLenum internalFormat
, GLuint width
, GLuint height
)
305 ASSERT(rb
->Name
== 0);
308 rb
->InternalFormat
= internalFormat
;
315 intel_resize_buffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
316 GLuint width
, GLuint height
)
320 _mesa_resize_framebuffer(ctx
, fb
, width
, height
);
322 fb
->Initialized
= true; /* XXX remove someday */
329 /* Make sure all window system renderbuffers are up to date */
330 for (i
= BUFFER_FRONT_LEFT
; i
<= BUFFER_BACK_RIGHT
; i
++) {
331 struct gl_renderbuffer
*rb
= fb
->Attachment
[i
].Renderbuffer
;
333 /* only resize if size is changing */
334 if (rb
&& (rb
->Width
!= width
|| rb
->Height
!= height
)) {
335 rb
->AllocStorage(ctx
, rb
, rb
->InternalFormat
, width
, height
);
341 /** Dummy function for gl_renderbuffer::AllocStorage() */
343 intel_nop_alloc_storage(struct gl_context
* ctx
, struct gl_renderbuffer
*rb
,
344 GLenum internalFormat
, GLuint width
, GLuint height
)
346 _mesa_problem(ctx
, "intel_op_alloc_storage should never be called.");
351 * Create a new intel_renderbuffer which corresponds to an on-screen window,
352 * not a user-created renderbuffer.
354 struct intel_renderbuffer
*
355 intel_create_renderbuffer(gl_format format
)
357 GET_CURRENT_CONTEXT(ctx
);
359 struct intel_renderbuffer
*irb
;
361 irb
= CALLOC_STRUCT(intel_renderbuffer
);
363 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "creating renderbuffer");
367 _mesa_init_renderbuffer(&irb
->Base
, 0);
368 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
369 irb
->Base
._BaseFormat
= _mesa_get_format_base_format(format
);
370 irb
->Base
.Format
= format
;
371 irb
->Base
.InternalFormat
= irb
->Base
._BaseFormat
;
372 irb
->Base
.DataType
= intel_mesa_format_to_rb_datatype(format
);
374 /* intel-specific methods */
375 irb
->Base
.Delete
= intel_delete_renderbuffer
;
376 irb
->Base
.AllocStorage
= intel_alloc_window_storage
;
377 irb
->Base
.GetPointer
= intel_get_pointer
;
383 struct gl_renderbuffer
*
384 intel_create_wrapped_renderbuffer(struct gl_context
* ctx
,
385 int width
, int height
,
389 * The name here is irrelevant, as long as its nonzero, because the
390 * renderbuffer never gets entered into Mesa's renderbuffer hash table.
394 struct intel_renderbuffer
*irb
= CALLOC_STRUCT(intel_renderbuffer
);
396 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "creating renderbuffer");
400 struct gl_renderbuffer
*rb
= &irb
->Base
;
401 _mesa_init_renderbuffer(rb
, name
);
402 rb
->ClassID
= INTEL_RB_CLASS
;
403 rb
->_BaseFormat
= _mesa_get_format_base_format(format
);
405 rb
->InternalFormat
= rb
->_BaseFormat
;
406 rb
->DataType
= intel_mesa_format_to_rb_datatype(format
);
415 * Create a new renderbuffer object.
416 * Typically called via glBindRenderbufferEXT().
418 static struct gl_renderbuffer
*
419 intel_new_renderbuffer(struct gl_context
* ctx
, GLuint name
)
421 /*struct intel_context *intel = intel_context(ctx); */
422 struct intel_renderbuffer
*irb
;
424 irb
= CALLOC_STRUCT(intel_renderbuffer
);
426 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "creating renderbuffer");
430 _mesa_init_renderbuffer(&irb
->Base
, name
);
431 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
433 /* intel-specific methods */
434 irb
->Base
.Delete
= intel_delete_renderbuffer
;
435 irb
->Base
.AllocStorage
= intel_alloc_renderbuffer_storage
;
436 irb
->Base
.GetPointer
= intel_get_pointer
;
437 /* span routines set in alloc_storage function */
444 * Called via glBindFramebufferEXT().
447 intel_bind_framebuffer(struct gl_context
* ctx
, GLenum target
,
448 struct gl_framebuffer
*fb
, struct gl_framebuffer
*fbread
)
450 if (target
== GL_FRAMEBUFFER_EXT
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
451 intel_draw_buffer(ctx
);
454 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
460 * Called via glFramebufferRenderbufferEXT().
463 intel_framebuffer_renderbuffer(struct gl_context
* ctx
,
464 struct gl_framebuffer
*fb
,
465 GLenum attachment
, struct gl_renderbuffer
*rb
)
467 DBG("Intel FramebufferRenderbuffer %u %u\n", fb
->Name
, rb
? rb
->Name
: 0);
471 _mesa_framebuffer_renderbuffer(ctx
, fb
, attachment
, rb
);
472 intel_draw_buffer(ctx
);
476 intel_update_tex_wrapper_regions(struct intel_context
*intel
,
477 struct intel_renderbuffer
*irb
,
478 struct intel_texture_image
*intel_image
);
481 intel_update_wrapper(struct gl_context
*ctx
, struct intel_renderbuffer
*irb
,
482 struct gl_texture_image
*texImage
)
484 struct intel_context
*intel
= intel_context(ctx
);
485 struct intel_texture_image
*intel_image
= intel_texture_image(texImage
);
486 int width
, height
, depth
;
488 if (!intel_span_supports_format(texImage
->TexFormat
)) {
489 DBG("Render to texture BAD FORMAT %s\n",
490 _mesa_get_format_name(texImage
->TexFormat
));
493 DBG("Render to texture %s\n", _mesa_get_format_name(texImage
->TexFormat
));
496 intel_miptree_get_dimensions_for_image(texImage
, &width
, &height
, &depth
);
498 irb
->Base
.Format
= texImage
->TexFormat
;
499 irb
->Base
.DataType
= intel_mesa_format_to_rb_datatype(texImage
->TexFormat
);
500 irb
->Base
.InternalFormat
= texImage
->InternalFormat
;
501 irb
->Base
._BaseFormat
= _mesa_base_tex_format(ctx
, irb
->Base
.InternalFormat
);
502 irb
->Base
.Width
= width
;
503 irb
->Base
.Height
= height
;
505 irb
->Base
.Delete
= intel_delete_renderbuffer
;
506 irb
->Base
.AllocStorage
= intel_nop_alloc_storage
;
508 if (intel_image
->stencil_rb
) {
509 /* The tex image has packed depth/stencil format, but is using separate
513 struct intel_renderbuffer
*depth_irb
=
514 intel_renderbuffer(intel_image
->depth_rb
);
516 /* Update the hiz region if necessary. */
517 ok
= intel_update_tex_wrapper_regions(intel
, depth_irb
, intel_image
);
522 /* The tex image shares its embedded depth and stencil renderbuffers with
523 * the renderbuffer wrapper. */
524 _mesa_reference_renderbuffer(&irb
->wrapped_depth
,
525 intel_image
->depth_rb
);
526 _mesa_reference_renderbuffer(&irb
->wrapped_stencil
,
527 intel_image
->stencil_rb
);
531 return intel_update_tex_wrapper_regions(intel
, irb
, intel_image
);
536 * FIXME: The handling of the hiz region is broken for mipmapped depth textures
537 * FIXME: because intel_finalize_mipmap_tree is unaware of it.
540 intel_update_tex_wrapper_regions(struct intel_context
*intel
,
541 struct intel_renderbuffer
*irb
,
542 struct intel_texture_image
*intel_image
)
544 struct gl_renderbuffer
*rb
= &irb
->Base
;
546 /* Point the renderbuffer's region to the texture's region. */
547 if (irb
->region
!= intel_image
->mt
->region
) {
548 intel_region_reference(&irb
->region
, intel_image
->mt
->region
);
551 /* Allocate the texture's hiz region if necessary. */
552 if (intel
->vtbl
.is_hiz_depth_format(intel
, rb
->Format
)
553 && !intel_image
->mt
->hiz_region
) {
554 intel_image
->mt
->hiz_region
=
555 intel_region_alloc(intel
->intelScreen
,
557 _mesa_get_format_bytes(rb
->Format
),
561 if (!intel_image
->mt
->hiz_region
)
565 /* Point the renderbuffer's hiz region to the texture's hiz region. */
566 if (irb
->hiz_region
!= intel_image
->mt
->hiz_region
) {
567 intel_region_reference(&irb
->hiz_region
, intel_image
->mt
->hiz_region
);
575 * When glFramebufferTexture[123]D is called this function sets up the
576 * gl_renderbuffer wrapper around the texture image.
577 * This will have the region info needed for hardware rendering.
579 static struct intel_renderbuffer
*
580 intel_wrap_texture(struct gl_context
* ctx
, struct gl_texture_image
*texImage
)
582 const GLuint name
= ~0; /* not significant, but distinct for debugging */
583 struct intel_renderbuffer
*irb
;
585 /* make an intel_renderbuffer to wrap the texture image */
586 irb
= CALLOC_STRUCT(intel_renderbuffer
);
588 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glFramebufferTexture");
592 _mesa_init_renderbuffer(&irb
->Base
, name
);
593 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
595 if (!intel_update_wrapper(ctx
, irb
, texImage
)) {
604 intel_renderbuffer_set_draw_offset(struct intel_renderbuffer
*irb
,
605 struct intel_texture_image
*intel_image
,
608 unsigned int dst_x
, dst_y
;
610 /* compute offset of the particular 2D image within the texture region */
611 intel_miptree_get_image_offset(intel_image
->mt
,
612 intel_image
->base
.Base
.Level
,
613 intel_image
->base
.Base
.Face
,
622 * Rendering to tiled buffers requires that the base address of the
623 * buffer be aligned to a page boundary. We generally render to
624 * textures by pointing the surface at the mipmap image level, which
625 * may not be aligned to a tile boundary.
627 * This function returns an appropriately-aligned base offset
628 * according to the tiling restrictions, plus any required x/y offset
632 intel_renderbuffer_tile_offsets(struct intel_renderbuffer
*irb
,
636 int cpp
= irb
->region
->cpp
;
637 uint32_t pitch
= irb
->region
->pitch
* cpp
;
639 if (irb
->region
->tiling
== I915_TILING_NONE
) {
642 return irb
->draw_x
* cpp
+ irb
->draw_y
* pitch
;
643 } else if (irb
->region
->tiling
== I915_TILING_X
) {
644 *tile_x
= irb
->draw_x
% (512 / cpp
);
645 *tile_y
= irb
->draw_y
% 8;
646 return ((irb
->draw_y
/ 8) * (8 * pitch
) +
647 (irb
->draw_x
- *tile_x
) / (512 / cpp
) * 4096);
649 assert(irb
->region
->tiling
== I915_TILING_Y
);
650 *tile_x
= irb
->draw_x
% (128 / cpp
);
651 *tile_y
= irb
->draw_y
% 32;
652 return ((irb
->draw_y
/ 32) * (32 * pitch
) +
653 (irb
->draw_x
- *tile_x
) / (128 / cpp
) * 4096);
659 need_tile_offset_workaround(struct brw_context
*brw
,
660 struct intel_renderbuffer
*irb
)
662 uint32_t tile_x
, tile_y
;
664 if (brw
->has_surface_tile_offset
)
667 intel_renderbuffer_tile_offsets(irb
, &tile_x
, &tile_y
);
669 return tile_x
!= 0 || tile_y
!= 0;
674 * Called by glFramebufferTexture[123]DEXT() (and other places) to
675 * prepare for rendering into texture memory. This might be called
676 * many times to choose different texture levels, cube faces, etc
677 * before intel_finish_render_texture() is ever called.
680 intel_render_texture(struct gl_context
* ctx
,
681 struct gl_framebuffer
*fb
,
682 struct gl_renderbuffer_attachment
*att
)
684 struct gl_texture_image
*image
= _mesa_get_attachment_teximage(att
);
685 struct intel_renderbuffer
*irb
= intel_renderbuffer(att
->Renderbuffer
);
686 struct intel_texture_image
*intel_image
= intel_texture_image(image
);
690 if (!intel_image
->mt
) {
691 /* Fallback on drawing to a texture that doesn't have a miptree
692 * (has a border, width/height 0, etc.)
694 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
695 _swrast_render_texture(ctx
, fb
, att
);
699 irb
= intel_wrap_texture(ctx
, image
);
701 /* bind the wrapper to the attachment point */
702 _mesa_reference_renderbuffer(&att
->Renderbuffer
, &irb
->Base
);
705 /* fallback to software rendering */
706 _swrast_render_texture(ctx
, fb
, att
);
711 if (!intel_update_wrapper(ctx
, irb
, image
)) {
712 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
713 _swrast_render_texture(ctx
, fb
, att
);
717 DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
719 att
->Texture
->Name
, image
->Width
, image
->Height
,
722 intel_renderbuffer_set_draw_offset(irb
, intel_image
, att
->Zoffset
);
723 intel_image
->used_as_render_target
= true;
726 if (need_tile_offset_workaround(brw_context(ctx
), irb
)) {
727 /* Original gen4 hardware couldn't draw to a non-tile-aligned
728 * destination in a miptree unless you actually setup your
729 * renderbuffer as a miptree and used the fragile
730 * lod/array_index/etc. controls to select the image. So,
731 * instead, we just make a new single-level miptree and render
734 struct intel_context
*intel
= intel_context(ctx
);
735 struct intel_mipmap_tree
*new_mt
;
736 int width
, height
, depth
;
738 intel_miptree_get_dimensions_for_image(image
, &width
, &height
, &depth
);
740 new_mt
= intel_miptree_create(intel
, image
->TexObject
->Target
,
741 intel_image
->base
.Base
.TexFormat
,
742 intel_image
->base
.Base
.Level
,
743 intel_image
->base
.Base
.Level
,
744 width
, height
, depth
,
747 intel_miptree_copy_teximage(intel
, intel_image
, new_mt
);
748 intel_renderbuffer_set_draw_offset(irb
, intel_image
, att
->Zoffset
);
750 intel_region_reference(&irb
->region
, intel_image
->mt
->region
);
751 intel_miptree_release(&new_mt
);
754 /* update drawing region, etc */
755 intel_draw_buffer(ctx
);
760 * Called by Mesa when rendering to a texture is done.
763 intel_finish_render_texture(struct gl_context
* ctx
,
764 struct gl_renderbuffer_attachment
*att
)
766 struct intel_context
*intel
= intel_context(ctx
);
767 struct gl_texture_object
*tex_obj
= att
->Texture
;
768 struct gl_texture_image
*image
=
769 tex_obj
->Image
[att
->CubeMapFace
][att
->TextureLevel
];
770 struct intel_texture_image
*intel_image
= intel_texture_image(image
);
772 DBG("Finish render texture tid %lx tex=%u\n",
773 _glthread_GetID(), att
->Texture
->Name
);
775 /* Flag that this image may now be validated into the object's miptree. */
777 intel_image
->used_as_render_target
= false;
779 /* Since we've (probably) rendered to the texture and will (likely) use
780 * it in the texture domain later on in this batchbuffer, flush the
781 * batch. Once again, we wish for a domain tracker in libdrm to cover
782 * usage inside of a batchbuffer like GEM does in the kernel.
784 intel_batchbuffer_emit_mi_flush(intel
);
788 * Do additional "completeness" testing of a framebuffer object.
791 intel_validate_framebuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
)
793 struct intel_context
*intel
= intel_context(ctx
);
794 const struct intel_renderbuffer
*depthRb
=
795 intel_get_renderbuffer(fb
, BUFFER_DEPTH
);
796 const struct intel_renderbuffer
*stencilRb
=
797 intel_get_renderbuffer(fb
, BUFFER_STENCIL
);
801 * The depth and stencil renderbuffers are the same renderbuffer or wrap
804 if (depthRb
&& stencilRb
) {
805 bool depth_stencil_are_same
;
806 if (depthRb
== stencilRb
)
807 depth_stencil_are_same
= true;
808 else if ((fb
->Attachment
[BUFFER_DEPTH
].Type
== GL_TEXTURE
) &&
809 (fb
->Attachment
[BUFFER_STENCIL
].Type
== GL_TEXTURE
) &&
810 (fb
->Attachment
[BUFFER_DEPTH
].Texture
->Name
==
811 fb
->Attachment
[BUFFER_STENCIL
].Texture
->Name
))
812 depth_stencil_are_same
= true;
814 depth_stencil_are_same
= false;
816 if (!intel
->has_separate_stencil
&& !depth_stencil_are_same
) {
817 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
821 for (i
= 0; i
< Elements(fb
->Attachment
); i
++) {
822 struct gl_renderbuffer
*rb
;
823 struct intel_renderbuffer
*irb
;
825 if (fb
->Attachment
[i
].Type
== GL_NONE
)
828 /* A supported attachment will have a Renderbuffer set either
829 * from being a Renderbuffer or being a texture that got the
830 * intel_wrap_texture() treatment.
832 rb
= fb
->Attachment
[i
].Renderbuffer
;
834 DBG("attachment without renderbuffer\n");
835 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
839 irb
= intel_renderbuffer(rb
);
841 DBG("software rendering renderbuffer\n");
842 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
846 if (!intel_span_supports_format(irb
->Base
.Format
) ||
847 !intel
->vtbl
.render_target_supported(irb
->Base
.Format
)) {
848 DBG("Unsupported texture/renderbuffer format attached: %s\n",
849 _mesa_get_format_name(irb
->Base
.Format
));
850 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
856 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
857 * We can do this when the dst renderbuffer is actually a texture and
858 * there is no scaling, mirroring or scissoring.
860 * \return new buffer mask indicating the buffers left to blit using the
864 intel_blit_framebuffer_copy_tex_sub_image(struct gl_context
*ctx
,
865 GLint srcX0
, GLint srcY0
,
866 GLint srcX1
, GLint srcY1
,
867 GLint dstX0
, GLint dstY0
,
868 GLint dstX1
, GLint dstY1
,
869 GLbitfield mask
, GLenum filter
)
871 if (mask
& GL_COLOR_BUFFER_BIT
) {
872 const struct gl_framebuffer
*drawFb
= ctx
->DrawBuffer
;
873 const struct gl_framebuffer
*readFb
= ctx
->ReadBuffer
;
874 const struct gl_renderbuffer_attachment
*drawAtt
=
875 &drawFb
->Attachment
[drawFb
->_ColorDrawBufferIndexes
[0]];
877 /* If the source and destination are the same size with no
878 mirroring, the rectangles are within the size of the
879 texture and there is no scissor then we can use
880 glCopyTexSubimage2D to implement the blit. This will end
881 up as a fast hardware blit on some drivers */
882 if (drawAtt
&& drawAtt
->Texture
&&
883 srcX0
- srcX1
== dstX0
- dstX1
&&
884 srcY0
- srcY1
== dstY0
- dstY1
&&
887 srcX0
>= 0 && srcX1
<= readFb
->Width
&&
888 srcY0
>= 0 && srcY1
<= readFb
->Height
&&
889 dstX0
>= 0 && dstX1
<= drawFb
->Width
&&
890 dstY0
>= 0 && dstY1
<= drawFb
->Height
&&
891 !ctx
->Scissor
.Enabled
) {
892 const struct gl_texture_object
*texObj
= drawAtt
->Texture
;
893 const GLuint dstLevel
= drawAtt
->TextureLevel
;
894 const GLenum target
= texObj
->Target
;
896 struct gl_texture_image
*texImage
=
897 _mesa_select_tex_image(ctx
, texObj
, target
, dstLevel
);
899 if (intel_copy_texsubimage(intel_context(ctx
),
900 intel_texture_image(texImage
),
903 srcX1
- srcX0
, /* width */
905 mask
&= ~GL_COLOR_BUFFER_BIT
;
913 intel_blit_framebuffer(struct gl_context
*ctx
,
914 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
915 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
916 GLbitfield mask
, GLenum filter
)
918 /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
919 mask
= intel_blit_framebuffer_copy_tex_sub_image(ctx
,
920 srcX0
, srcY0
, srcX1
, srcY1
,
921 dstX0
, dstY0
, dstX1
, dstY1
,
926 _mesa_meta_BlitFramebuffer(ctx
,
927 srcX0
, srcY0
, srcX1
, srcY1
,
928 dstX0
, dstY0
, dstX1
, dstY1
,
933 * Do one-time context initializations related to GL_EXT_framebuffer_object.
934 * Hook in device driver functions.
937 intel_fbo_init(struct intel_context
*intel
)
939 intel
->ctx
.Driver
.NewFramebuffer
= intel_new_framebuffer
;
940 intel
->ctx
.Driver
.NewRenderbuffer
= intel_new_renderbuffer
;
941 intel
->ctx
.Driver
.BindFramebuffer
= intel_bind_framebuffer
;
942 intel
->ctx
.Driver
.FramebufferRenderbuffer
= intel_framebuffer_renderbuffer
;
943 intel
->ctx
.Driver
.RenderTexture
= intel_render_texture
;
944 intel
->ctx
.Driver
.FinishRenderTexture
= intel_finish_render_texture
;
945 intel
->ctx
.Driver
.ResizeBuffers
= intel_resize_buffers
;
946 intel
->ctx
.Driver
.ValidateFramebuffer
= intel_validate_framebuffer
;
947 intel
->ctx
.Driver
.BlitFramebuffer
= intel_blit_framebuffer
;
949 #if FEATURE_OES_EGL_image
950 intel
->ctx
.Driver
.EGLImageTargetRenderbufferStorage
=
951 intel_image_target_renderbuffer_storage
;