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
, GL_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 irb
= intel_renderbuffer(rb
);
273 intel_region_reference(&irb
->region
, image
->region
);
275 rb
->InternalFormat
= image
->internal_format
;
276 rb
->Width
= image
->region
->width
;
277 rb
->Height
= image
->region
->height
;
278 rb
->Format
= image
->format
;
279 rb
->DataType
= image
->data_type
;
280 rb
->_BaseFormat
= _mesa_base_fbo_format(&intel
->ctx
,
281 image
->internal_format
);
286 * Called for each hardware renderbuffer when a _window_ is resized.
287 * Just update fields.
288 * Not used for user-created renderbuffers!
291 intel_alloc_window_storage(struct gl_context
* ctx
, struct gl_renderbuffer
*rb
,
292 GLenum internalFormat
, GLuint width
, GLuint height
)
294 ASSERT(rb
->Name
== 0);
297 rb
->InternalFormat
= internalFormat
;
304 intel_resize_buffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
305 GLuint width
, GLuint height
)
309 _mesa_resize_framebuffer(ctx
, fb
, width
, height
);
311 fb
->Initialized
= GL_TRUE
; /* XXX remove someday */
318 /* Make sure all window system renderbuffers are up to date */
319 for (i
= BUFFER_FRONT_LEFT
; i
<= BUFFER_BACK_RIGHT
; i
++) {
320 struct gl_renderbuffer
*rb
= fb
->Attachment
[i
].Renderbuffer
;
322 /* only resize if size is changing */
323 if (rb
&& (rb
->Width
!= width
|| rb
->Height
!= height
)) {
324 rb
->AllocStorage(ctx
, rb
, rb
->InternalFormat
, width
, height
);
330 /** Dummy function for gl_renderbuffer::AllocStorage() */
332 intel_nop_alloc_storage(struct gl_context
* ctx
, struct gl_renderbuffer
*rb
,
333 GLenum internalFormat
, GLuint width
, GLuint height
)
335 _mesa_problem(ctx
, "intel_op_alloc_storage should never be called.");
340 * Create a new intel_renderbuffer which corresponds to an on-screen window,
341 * not a user-created renderbuffer.
343 struct intel_renderbuffer
*
344 intel_create_renderbuffer(gl_format format
)
346 GET_CURRENT_CONTEXT(ctx
);
348 struct intel_renderbuffer
*irb
;
350 irb
= CALLOC_STRUCT(intel_renderbuffer
);
352 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "creating renderbuffer");
356 _mesa_init_renderbuffer(&irb
->Base
, 0);
357 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
358 irb
->Base
._BaseFormat
= _mesa_get_format_base_format(format
);
359 irb
->Base
.Format
= format
;
360 irb
->Base
.InternalFormat
= irb
->Base
._BaseFormat
;
361 irb
->Base
.DataType
= intel_mesa_format_to_rb_datatype(format
);
363 /* intel-specific methods */
364 irb
->Base
.Delete
= intel_delete_renderbuffer
;
365 irb
->Base
.AllocStorage
= intel_alloc_window_storage
;
366 irb
->Base
.GetPointer
= intel_get_pointer
;
372 struct gl_renderbuffer
*
373 intel_create_wrapped_renderbuffer(struct gl_context
* ctx
,
374 int width
, int height
,
378 * The name here is irrelevant, as long as its nonzero, because the
379 * renderbuffer never gets entered into Mesa's renderbuffer hash table.
383 struct intel_renderbuffer
*irb
= CALLOC_STRUCT(intel_renderbuffer
);
385 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "creating renderbuffer");
389 struct gl_renderbuffer
*rb
= &irb
->Base
;
390 _mesa_init_renderbuffer(rb
, name
);
391 rb
->ClassID
= INTEL_RB_CLASS
;
392 rb
->_BaseFormat
= _mesa_get_format_base_format(format
);
394 rb
->InternalFormat
= rb
->_BaseFormat
;
395 rb
->DataType
= intel_mesa_format_to_rb_datatype(format
);
404 * Create a new renderbuffer object.
405 * Typically called via glBindRenderbufferEXT().
407 static struct gl_renderbuffer
*
408 intel_new_renderbuffer(struct gl_context
* ctx
, GLuint name
)
410 /*struct intel_context *intel = intel_context(ctx); */
411 struct intel_renderbuffer
*irb
;
413 irb
= CALLOC_STRUCT(intel_renderbuffer
);
415 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "creating renderbuffer");
419 _mesa_init_renderbuffer(&irb
->Base
, name
);
420 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
422 /* intel-specific methods */
423 irb
->Base
.Delete
= intel_delete_renderbuffer
;
424 irb
->Base
.AllocStorage
= intel_alloc_renderbuffer_storage
;
425 irb
->Base
.GetPointer
= intel_get_pointer
;
426 /* span routines set in alloc_storage function */
433 * Called via glBindFramebufferEXT().
436 intel_bind_framebuffer(struct gl_context
* ctx
, GLenum target
,
437 struct gl_framebuffer
*fb
, struct gl_framebuffer
*fbread
)
439 if (target
== GL_FRAMEBUFFER_EXT
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
440 intel_draw_buffer(ctx
, fb
);
443 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
449 * Called via glFramebufferRenderbufferEXT().
452 intel_framebuffer_renderbuffer(struct gl_context
* ctx
,
453 struct gl_framebuffer
*fb
,
454 GLenum attachment
, struct gl_renderbuffer
*rb
)
456 DBG("Intel FramebufferRenderbuffer %u %u\n", fb
->Name
, rb
? rb
->Name
: 0);
460 _mesa_framebuffer_renderbuffer(ctx
, fb
, attachment
, rb
);
461 intel_draw_buffer(ctx
, fb
);
465 intel_update_tex_wrapper_regions(struct intel_context
*intel
,
466 struct intel_renderbuffer
*irb
,
467 struct intel_texture_image
*intel_image
);
470 intel_update_wrapper(struct gl_context
*ctx
, struct intel_renderbuffer
*irb
,
471 struct gl_texture_image
*texImage
)
473 struct intel_context
*intel
= intel_context(ctx
);
474 struct intel_texture_image
*intel_image
= intel_texture_image(texImage
);
476 if (!intel_span_supports_format(texImage
->TexFormat
)) {
477 DBG("Render to texture BAD FORMAT %s\n",
478 _mesa_get_format_name(texImage
->TexFormat
));
481 DBG("Render to texture %s\n", _mesa_get_format_name(texImage
->TexFormat
));
484 irb
->Base
.Format
= texImage
->TexFormat
;
485 irb
->Base
.DataType
= intel_mesa_format_to_rb_datatype(texImage
->TexFormat
);
486 irb
->Base
.InternalFormat
= texImage
->InternalFormat
;
487 irb
->Base
._BaseFormat
= _mesa_base_tex_format(ctx
, irb
->Base
.InternalFormat
);
488 irb
->Base
.Width
= texImage
->Width
;
489 irb
->Base
.Height
= texImage
->Height
;
491 irb
->Base
.Delete
= intel_delete_renderbuffer
;
492 irb
->Base
.AllocStorage
= intel_nop_alloc_storage
;
494 if (intel_image
->stencil_rb
) {
495 /* The tex image has packed depth/stencil format, but is using separate
499 struct intel_renderbuffer
*depth_irb
=
500 intel_renderbuffer(intel_image
->depth_rb
);
502 /* Update the hiz region if necessary. */
503 ok
= intel_update_tex_wrapper_regions(intel
, depth_irb
, intel_image
);
508 /* The tex image shares its embedded depth and stencil renderbuffers with
509 * the renderbuffer wrapper. */
510 if (irb
->wrapped_depth
!= intel_image
->depth_rb
) {
511 _mesa_reference_renderbuffer(&irb
->wrapped_depth
,
512 intel_image
->depth_rb
);
514 if (irb
->wrapped_stencil
!= intel_image
->stencil_rb
) {
515 _mesa_reference_renderbuffer(&irb
->wrapped_stencil
,
516 intel_image
->stencil_rb
);
522 return intel_update_tex_wrapper_regions(intel
, irb
, intel_image
);
527 * FIXME: The handling of the hiz region is broken for mipmapped depth textures
528 * FIXME: because intel_finalize_mipmap_tree is unaware of it.
531 intel_update_tex_wrapper_regions(struct intel_context
*intel
,
532 struct intel_renderbuffer
*irb
,
533 struct intel_texture_image
*intel_image
)
535 struct gl_renderbuffer
*rb
= &irb
->Base
;
537 /* Point the renderbuffer's region to the texture's region. */
538 if (irb
->region
!= intel_image
->mt
->region
) {
539 intel_region_reference(&irb
->region
, intel_image
->mt
->region
);
542 /* Allocate the texture's hiz region if necessary. */
543 if (intel
->vtbl
.is_hiz_depth_format(intel
, rb
->Format
)
544 && !intel_image
->mt
->hiz_region
) {
545 intel_image
->mt
->hiz_region
=
546 intel_region_alloc(intel
->intelScreen
,
548 _mesa_get_format_bytes(rb
->Format
),
552 if (!intel_image
->mt
->hiz_region
)
556 /* Point the renderbuffer's hiz region to the texture's hiz region. */
557 if (irb
->hiz_region
!= intel_image
->mt
->hiz_region
) {
558 intel_region_reference(&irb
->hiz_region
, intel_image
->mt
->hiz_region
);
566 * When glFramebufferTexture[123]D is called this function sets up the
567 * gl_renderbuffer wrapper around the texture image.
568 * This will have the region info needed for hardware rendering.
570 static struct intel_renderbuffer
*
571 intel_wrap_texture(struct gl_context
* ctx
, struct gl_texture_image
*texImage
)
573 const GLuint name
= ~0; /* not significant, but distinct for debugging */
574 struct intel_renderbuffer
*irb
;
576 /* make an intel_renderbuffer to wrap the texture image */
577 irb
= CALLOC_STRUCT(intel_renderbuffer
);
579 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glFramebufferTexture");
583 _mesa_init_renderbuffer(&irb
->Base
, name
);
584 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
586 if (!intel_update_wrapper(ctx
, irb
, texImage
)) {
595 intel_renderbuffer_set_draw_offset(struct intel_renderbuffer
*irb
,
596 struct intel_texture_image
*intel_image
,
599 struct intel_mipmap_tree
*mt
= intel_image
->mt
;
600 unsigned int dst_x
, dst_y
;
602 /* compute offset of the particular 2D image within the texture region */
603 intel_miptree_get_image_offset(intel_image
->mt
,
609 irb
->draw_offset
= (dst_y
* mt
->region
->pitch
+ dst_x
) * mt
->cpp
;
615 * Rendering to tiled buffers requires that the base address of the
616 * buffer be aligned to a page boundary. We generally render to
617 * textures by pointing the surface at the mipmap image level, which
618 * may not be aligned to a tile boundary.
620 * This function returns an appropriately-aligned base offset
621 * according to the tiling restrictions, plus any required x/y offset
625 intel_renderbuffer_tile_offsets(struct intel_renderbuffer
*irb
,
629 int cpp
= irb
->region
->cpp
;
630 uint32_t pitch
= irb
->region
->pitch
* cpp
;
632 if (irb
->region
->tiling
== I915_TILING_NONE
) {
635 return irb
->draw_x
* cpp
+ irb
->draw_y
* pitch
;
636 } else if (irb
->region
->tiling
== I915_TILING_X
) {
637 *tile_x
= irb
->draw_x
% (512 / cpp
);
638 *tile_y
= irb
->draw_y
% 8;
639 return ((irb
->draw_y
/ 8) * (8 * pitch
) +
640 (irb
->draw_x
- *tile_x
) / (512 / cpp
) * 4096);
642 assert(irb
->region
->tiling
== I915_TILING_Y
);
643 *tile_x
= irb
->draw_x
% (128 / cpp
);
644 *tile_y
= irb
->draw_y
% 32;
645 return ((irb
->draw_y
/ 32) * (32 * pitch
) +
646 (irb
->draw_x
- *tile_x
) / (128 / cpp
) * 4096);
651 * Called by glFramebufferTexture[123]DEXT() (and other places) to
652 * prepare for rendering into texture memory. This might be called
653 * many times to choose different texture levels, cube faces, etc
654 * before intel_finish_render_texture() is ever called.
657 intel_render_texture(struct gl_context
* ctx
,
658 struct gl_framebuffer
*fb
,
659 struct gl_renderbuffer_attachment
*att
)
661 struct gl_texture_image
*image
= _mesa_get_attachment_teximage(att
);
662 struct intel_renderbuffer
*irb
= intel_renderbuffer(att
->Renderbuffer
);
663 struct intel_texture_image
*intel_image
= intel_texture_image(image
);
667 if (!intel_image
->mt
) {
668 /* Fallback on drawing to a texture that doesn't have a miptree
669 * (has a border, width/height 0, etc.)
671 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
672 _swrast_render_texture(ctx
, fb
, att
);
676 irb
= intel_wrap_texture(ctx
, image
);
678 /* bind the wrapper to the attachment point */
679 _mesa_reference_renderbuffer(&att
->Renderbuffer
, &irb
->Base
);
682 /* fallback to software rendering */
683 _swrast_render_texture(ctx
, fb
, att
);
688 if (!intel_update_wrapper(ctx
, irb
, image
)) {
689 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
690 _swrast_render_texture(ctx
, fb
, att
);
694 DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
696 att
->Texture
->Name
, image
->Width
, image
->Height
,
699 intel_renderbuffer_set_draw_offset(irb
, intel_image
, att
->Zoffset
);
700 intel_image
->used_as_render_target
= GL_TRUE
;
703 if (!brw_context(ctx
)->has_surface_tile_offset
&&
704 (irb
->draw_offset
& 4095) != 0) {
705 /* Original gen4 hardware couldn't draw to a non-tile-aligned
706 * destination in a miptree unless you actually setup your
707 * renderbuffer as a miptree and used the fragile
708 * lod/array_index/etc. controls to select the image. So,
709 * instead, we just make a new single-level miptree and render
712 struct intel_context
*intel
= intel_context(ctx
);
713 struct intel_mipmap_tree
*old_mt
= intel_image
->mt
;
714 struct intel_mipmap_tree
*new_mt
;
716 new_mt
= intel_miptree_create(intel
, image
->TexObject
->Target
,
717 intel_image
->base
.TexFormat
,
720 intel_image
->base
.Width
,
721 intel_image
->base
.Height
,
722 intel_image
->base
.Depth
,
725 intel_miptree_image_copy(intel
,
731 intel_miptree_release(intel
, &intel_image
->mt
);
732 intel_image
->mt
= new_mt
;
733 intel_renderbuffer_set_draw_offset(irb
, intel_image
, att
->Zoffset
);
735 intel_region_reference(&irb
->region
, intel_image
->mt
->region
);
738 /* update drawing region, etc */
739 intel_draw_buffer(ctx
, fb
);
744 * Called by Mesa when rendering to a texture is done.
747 intel_finish_render_texture(struct gl_context
* ctx
,
748 struct gl_renderbuffer_attachment
*att
)
750 struct intel_context
*intel
= intel_context(ctx
);
751 struct gl_texture_object
*tex_obj
= att
->Texture
;
752 struct gl_texture_image
*image
=
753 tex_obj
->Image
[att
->CubeMapFace
][att
->TextureLevel
];
754 struct intel_texture_image
*intel_image
= intel_texture_image(image
);
756 DBG("Finish render texture tid %lx tex=%u\n",
757 _glthread_GetID(), att
->Texture
->Name
);
759 /* Flag that this image may now be validated into the object's miptree. */
761 intel_image
->used_as_render_target
= GL_FALSE
;
763 /* Since we've (probably) rendered to the texture and will (likely) use
764 * it in the texture domain later on in this batchbuffer, flush the
765 * batch. Once again, we wish for a domain tracker in libdrm to cover
766 * usage inside of a batchbuffer like GEM does in the kernel.
768 intel_batchbuffer_emit_mi_flush(intel
);
772 * Do additional "completeness" testing of a framebuffer object.
775 intel_validate_framebuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
)
777 struct intel_context
*intel
= intel_context(ctx
);
778 const struct intel_renderbuffer
*depthRb
=
779 intel_get_renderbuffer(fb
, BUFFER_DEPTH
);
780 const struct intel_renderbuffer
*stencilRb
=
781 intel_get_renderbuffer(fb
, BUFFER_STENCIL
);
785 * The depth and stencil renderbuffers are the same renderbuffer or wrap
788 if (depthRb
&& stencilRb
) {
789 bool depth_stencil_are_same
;
790 if (depthRb
== stencilRb
)
791 depth_stencil_are_same
= true;
792 else if ((fb
->Attachment
[BUFFER_DEPTH
].Type
== GL_TEXTURE
) &&
793 (fb
->Attachment
[BUFFER_STENCIL
].Type
== GL_TEXTURE
) &&
794 (fb
->Attachment
[BUFFER_DEPTH
].Texture
->Name
==
795 fb
->Attachment
[BUFFER_STENCIL
].Texture
->Name
))
796 depth_stencil_are_same
= true;
798 depth_stencil_are_same
= false;
800 if (!intel
->has_separate_stencil
&& !depth_stencil_are_same
) {
801 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
805 for (i
= 0; i
< Elements(fb
->Attachment
); i
++) {
806 struct gl_renderbuffer
*rb
;
807 struct intel_renderbuffer
*irb
;
809 if (fb
->Attachment
[i
].Type
== GL_NONE
)
812 /* A supported attachment will have a Renderbuffer set either
813 * from being a Renderbuffer or being a texture that got the
814 * intel_wrap_texture() treatment.
816 rb
= fb
->Attachment
[i
].Renderbuffer
;
818 DBG("attachment without renderbuffer\n");
819 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
823 irb
= intel_renderbuffer(rb
);
825 DBG("software rendering renderbuffer\n");
826 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
830 if (!intel_span_supports_format(irb
->Base
.Format
) ||
831 !intel
->vtbl
.render_target_supported(irb
->Base
.Format
)) {
832 DBG("Unsupported texture/renderbuffer format attached: %s\n",
833 _mesa_get_format_name(irb
->Base
.Format
));
834 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
840 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
841 * We can do this when the dst renderbuffer is actually a texture and
842 * there is no scaling, mirroring or scissoring.
844 * \return new buffer mask indicating the buffers left to blit using the
848 intel_blit_framebuffer_copy_tex_sub_image(struct gl_context
*ctx
,
849 GLint srcX0
, GLint srcY0
,
850 GLint srcX1
, GLint srcY1
,
851 GLint dstX0
, GLint dstY0
,
852 GLint dstX1
, GLint dstY1
,
853 GLbitfield mask
, GLenum filter
)
855 if (mask
& GL_COLOR_BUFFER_BIT
) {
856 const struct gl_framebuffer
*drawFb
= ctx
->DrawBuffer
;
857 const struct gl_framebuffer
*readFb
= ctx
->ReadBuffer
;
858 const struct gl_renderbuffer_attachment
*drawAtt
=
859 &drawFb
->Attachment
[drawFb
->_ColorDrawBufferIndexes
[0]];
861 /* If the source and destination are the same size with no
862 mirroring, the rectangles are within the size of the
863 texture and there is no scissor then we can use
864 glCopyTexSubimage2D to implement the blit. This will end
865 up as a fast hardware blit on some drivers */
866 if (drawAtt
&& drawAtt
->Texture
&&
867 srcX0
- srcX1
== dstX0
- dstX1
&&
868 srcY0
- srcY1
== dstY0
- dstY1
&&
871 srcX0
>= 0 && srcX1
<= readFb
->Width
&&
872 srcY0
>= 0 && srcY1
<= readFb
->Height
&&
873 dstX0
>= 0 && dstX1
<= drawFb
->Width
&&
874 dstY0
>= 0 && dstY1
<= drawFb
->Height
&&
875 !ctx
->Scissor
.Enabled
) {
876 const struct gl_texture_object
*texObj
= drawAtt
->Texture
;
877 const GLuint dstLevel
= drawAtt
->TextureLevel
;
878 const GLenum target
= texObj
->Target
;
880 struct gl_texture_image
*texImage
=
881 _mesa_select_tex_image(ctx
, texObj
, target
, dstLevel
);
882 GLenum internalFormat
= texImage
->InternalFormat
;
884 if (intel_copy_texsubimage(intel_context(ctx
), target
,
885 intel_texture_image(texImage
),
889 srcX1
- srcX0
, /* width */
891 mask
&= ~GL_COLOR_BUFFER_BIT
;
899 intel_blit_framebuffer(struct gl_context
*ctx
,
900 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
901 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
902 GLbitfield mask
, GLenum filter
)
904 /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
905 mask
= intel_blit_framebuffer_copy_tex_sub_image(ctx
,
906 srcX0
, srcY0
, srcX1
, srcY1
,
907 dstX0
, dstY0
, dstX1
, dstY1
,
912 _mesa_meta_BlitFramebuffer(ctx
,
913 srcX0
, srcY0
, srcX1
, srcY1
,
914 dstX0
, dstY0
, dstX1
, dstY1
,
919 * Do one-time context initializations related to GL_EXT_framebuffer_object.
920 * Hook in device driver functions.
923 intel_fbo_init(struct intel_context
*intel
)
925 intel
->ctx
.Driver
.NewFramebuffer
= intel_new_framebuffer
;
926 intel
->ctx
.Driver
.NewRenderbuffer
= intel_new_renderbuffer
;
927 intel
->ctx
.Driver
.BindFramebuffer
= intel_bind_framebuffer
;
928 intel
->ctx
.Driver
.FramebufferRenderbuffer
= intel_framebuffer_renderbuffer
;
929 intel
->ctx
.Driver
.RenderTexture
= intel_render_texture
;
930 intel
->ctx
.Driver
.FinishRenderTexture
= intel_finish_render_texture
;
931 intel
->ctx
.Driver
.ResizeBuffers
= intel_resize_buffers
;
932 intel
->ctx
.Driver
.ValidateFramebuffer
= intel_validate_framebuffer
;
933 intel
->ctx
.Driver
.BlitFramebuffer
= intel_blit_framebuffer
;
935 #if FEATURE_OES_EGL_image
936 intel
->ctx
.Driver
.EGLImageTargetRenderbufferStorage
=
937 intel_image_target_renderbuffer_storage
;