intel_fbo.c revision 84294fe26ca5860c34e6541f633be4d093ab57f2
1/**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28
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 "main/texrender.h"
39#include "drivers/common/meta.h"
40
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"
49#ifndef I915
50#include "brw_context.h"
51#endif
52
53#define FILE_DEBUG_FLAG DEBUG_FBO
54
55
56/**
57 * Create a new framebuffer object.
58 */
59static struct gl_framebuffer *
60intel_new_framebuffer(struct gl_context * ctx, GLuint name)
61{
62   /* Only drawable state in intel_framebuffer at this time, just use Mesa's
63    * class
64    */
65   return _mesa_new_framebuffer(ctx, name);
66}
67
68
69/** Called by gl_renderbuffer::Delete() */
70static void
71intel_delete_renderbuffer(struct gl_renderbuffer *rb)
72{
73   GET_CURRENT_CONTEXT(ctx);
74   struct intel_context *intel = intel_context(ctx);
75   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
76
77   ASSERT(irb);
78
79   if (intel && irb->region) {
80      intel_region_release(&irb->region);
81   }
82   if (intel && irb->hiz_region) {
83      intel_region_release(&irb->hiz_region);
84   }
85
86   free(irb);
87}
88
89
90/**
91 * Return a pointer to a specific pixel in a renderbuffer.
92 */
93static void *
94intel_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
95                  GLint x, GLint y)
96{
97   /* By returning NULL we force all software rendering to go through
98    * the span routines.
99    */
100   return NULL;
101}
102
103
104/**
105 * Called via glRenderbufferStorageEXT() to set the format and allocate
106 * storage for a user-created renderbuffer.
107 */
108static GLboolean
109intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
110                                 GLenum internalFormat,
111                                 GLuint width, GLuint height)
112{
113   struct intel_context *intel = intel_context(ctx);
114   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
115   int cpp, tiling;
116
117   ASSERT(rb->Name != 0);
118
119   switch (internalFormat) {
120   default:
121      /* Use the same format-choice logic as for textures.
122       * Renderbuffers aren't any different from textures for us,
123       * except they're less useful because you can't texture with
124       * them.
125       */
126      rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat,
127							 GL_NONE, GL_NONE);
128      break;
129   case GL_STENCIL_INDEX:
130   case GL_STENCIL_INDEX1_EXT:
131   case GL_STENCIL_INDEX4_EXT:
132   case GL_STENCIL_INDEX8_EXT:
133   case GL_STENCIL_INDEX16_EXT:
134      /* These aren't actual texture formats, so force them here. */
135      if (intel->has_separate_stencil) {
136	 rb->Format = MESA_FORMAT_S8;
137      } else {
138	 assert(!intel->must_use_separate_stencil);
139	 rb->Format = MESA_FORMAT_S8_Z24;
140      }
141      break;
142   }
143
144   rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
145   rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
146   cpp = _mesa_get_format_bytes(rb->Format);
147
148   intel_flush(ctx);
149
150   /* free old region */
151   if (irb->region) {
152      intel_region_release(&irb->region);
153   }
154   if (irb->hiz_region) {
155      intel_region_release(&irb->hiz_region);
156   }
157
158   /* allocate new memory region/renderbuffer */
159
160   /* alloc hardware renderbuffer */
161   DBG("Allocating %d x %d Intel RBO\n", width, height);
162
163   tiling = I915_TILING_NONE;
164   if (intel->use_texture_tiling) {
165      GLenum base_format = _mesa_get_format_base_format(rb->Format);
166
167      if (intel->gen >= 4 && (base_format == GL_DEPTH_COMPONENT ||
168			      base_format == GL_STENCIL_INDEX ||
169			      base_format == GL_DEPTH_STENCIL))
170	 tiling = I915_TILING_Y;
171      else
172	 tiling = I915_TILING_X;
173   }
174
175   if (irb->Base.Format == MESA_FORMAT_S8) {
176      /*
177       * The stencil buffer has quirky pitch requirements.  From Vol 2a,
178       * 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
179       *    The pitch must be set to 2x the value computed based on width, as
180       *    the stencil buffer is stored with two rows interleaved.
181       * To accomplish this, we resort to the nasty hack of doubling the drm
182       * region's cpp and halving its height.
183       *
184       * If we neglect to double the pitch, then drm_intel_gem_bo_map_gtt()
185       * maps the memory incorrectly.
186       */
187      irb->region = intel_region_alloc(intel->intelScreen,
188				       I915_TILING_Y,
189				       cpp * 2,
190				       width,
191				       height / 2,
192				       GL_TRUE);
193   } else {
194      irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp,
195				       width, height, GL_TRUE);
196   }
197
198   if (!irb->region)
199      return GL_FALSE;       /* out of memory? */
200
201   ASSERT(irb->region->buffer);
202
203   if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
204      irb->hiz_region = intel_region_alloc(intel->intelScreen,
205                                           I915_TILING_Y,
206                                           irb->region->cpp,
207                                           irb->region->width,
208                                           irb->region->height,
209                                           GL_TRUE);
210      if (!irb->hiz_region) {
211         intel_region_release(&irb->region);
212         return GL_FALSE;
213      }
214   }
215
216   rb->Width = width;
217   rb->Height = height;
218
219   return GL_TRUE;
220}
221
222
223#if FEATURE_OES_EGL_image
224static void
225intel_image_target_renderbuffer_storage(struct gl_context *ctx,
226					struct gl_renderbuffer *rb,
227					void *image_handle)
228{
229   struct intel_context *intel = intel_context(ctx);
230   struct intel_renderbuffer *irb;
231   __DRIscreen *screen;
232   __DRIimage *image;
233
234   screen = intel->intelScreen->driScrnPriv;
235   image = screen->dri2.image->lookupEGLImage(screen, image_handle,
236					      screen->loaderPrivate);
237   if (image == NULL)
238      return;
239
240   irb = intel_renderbuffer(rb);
241   if (irb->region)
242      intel_region_release(&irb->region);
243   intel_region_reference(&irb->region, image->region);
244
245   rb->InternalFormat = image->internal_format;
246   rb->Width = image->region->width;
247   rb->Height = image->region->height;
248   rb->Format = image->format;
249   rb->DataType = image->data_type;
250   rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
251					   image->internal_format);
252}
253#endif
254
255/**
256 * Called for each hardware renderbuffer when a _window_ is resized.
257 * Just update fields.
258 * Not used for user-created renderbuffers!
259 */
260static GLboolean
261intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
262                           GLenum internalFormat, GLuint width, GLuint height)
263{
264   ASSERT(rb->Name == 0);
265   rb->Width = width;
266   rb->Height = height;
267   rb->InternalFormat = internalFormat;
268
269   return GL_TRUE;
270}
271
272
273static void
274intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
275		     GLuint width, GLuint height)
276{
277   int i;
278
279   _mesa_resize_framebuffer(ctx, fb, width, height);
280
281   fb->Initialized = GL_TRUE; /* XXX remove someday */
282
283   if (fb->Name != 0) {
284      return;
285   }
286
287
288   /* Make sure all window system renderbuffers are up to date */
289   for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) {
290      struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
291
292      /* only resize if size is changing */
293      if (rb && (rb->Width != width || rb->Height != height)) {
294	 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
295      }
296   }
297}
298
299
300/** Dummy function for gl_renderbuffer::AllocStorage() */
301static GLboolean
302intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
303                        GLenum internalFormat, GLuint width, GLuint height)
304{
305   _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
306   return GL_FALSE;
307}
308
309
310void
311intel_renderbuffer_set_region(struct intel_context *intel,
312			      struct intel_renderbuffer *rb,
313			      struct intel_region *region)
314{
315   struct intel_region *old;
316
317   old = rb->region;
318   rb->region = NULL;
319   intel_region_reference(&rb->region, region);
320   intel_region_release(&old);
321}
322
323
324void
325intel_renderbuffer_set_hiz_region(struct intel_context *intel,
326				  struct intel_renderbuffer *rb,
327				  struct intel_region *region)
328{
329   struct intel_region *old = rb->hiz_region;
330   rb->hiz_region = NULL;
331   intel_region_reference(&rb->hiz_region, region);
332   intel_region_release(&old);
333}
334
335
336/**
337 * Create a new intel_renderbuffer which corresponds to an on-screen window,
338 * not a user-created renderbuffer.
339 */
340struct intel_renderbuffer *
341intel_create_renderbuffer(gl_format format)
342{
343   GET_CURRENT_CONTEXT(ctx);
344
345   struct intel_renderbuffer *irb;
346
347   irb = CALLOC_STRUCT(intel_renderbuffer);
348   if (!irb) {
349      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
350      return NULL;
351   }
352
353   _mesa_init_renderbuffer(&irb->Base, 0);
354   irb->Base.ClassID = INTEL_RB_CLASS;
355   irb->Base._BaseFormat = _mesa_get_format_base_format(format);
356   irb->Base.Format = format;
357   irb->Base.InternalFormat = irb->Base._BaseFormat;
358   irb->Base.DataType = intel_mesa_format_to_rb_datatype(format);
359
360   /* intel-specific methods */
361   irb->Base.Delete = intel_delete_renderbuffer;
362   irb->Base.AllocStorage = intel_alloc_window_storage;
363   irb->Base.GetPointer = intel_get_pointer;
364
365   return irb;
366}
367
368
369/**
370 * Create a new renderbuffer object.
371 * Typically called via glBindRenderbufferEXT().
372 */
373static struct gl_renderbuffer *
374intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
375{
376   /*struct intel_context *intel = intel_context(ctx); */
377   struct intel_renderbuffer *irb;
378
379   irb = CALLOC_STRUCT(intel_renderbuffer);
380   if (!irb) {
381      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
382      return NULL;
383   }
384
385   _mesa_init_renderbuffer(&irb->Base, name);
386   irb->Base.ClassID = INTEL_RB_CLASS;
387
388   /* intel-specific methods */
389   irb->Base.Delete = intel_delete_renderbuffer;
390   irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
391   irb->Base.GetPointer = intel_get_pointer;
392   /* span routines set in alloc_storage function */
393
394   return &irb->Base;
395}
396
397
398/**
399 * Called via glBindFramebufferEXT().
400 */
401static void
402intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
403                       struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
404{
405   if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
406      intel_draw_buffer(ctx, fb);
407   }
408   else {
409      /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
410   }
411}
412
413
414/**
415 * Called via glFramebufferRenderbufferEXT().
416 */
417static void
418intel_framebuffer_renderbuffer(struct gl_context * ctx,
419                               struct gl_framebuffer *fb,
420                               GLenum attachment, struct gl_renderbuffer *rb)
421{
422   DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
423
424   intel_flush(ctx);
425
426   _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
427   intel_draw_buffer(ctx, fb);
428}
429
430
431static GLboolean
432intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb,
433		     struct gl_texture_image *texImage)
434{
435   struct intel_context *intel = intel_context(ctx);
436   struct intel_texture_image *intel_image = intel_texture_image(texImage);
437
438   if (!intel_span_supports_format(texImage->TexFormat)) {
439      DBG("Render to texture BAD FORMAT %s\n",
440	  _mesa_get_format_name(texImage->TexFormat));
441      return GL_FALSE;
442   } else {
443      DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat));
444   }
445
446   irb->Base.Format = texImage->TexFormat;
447   irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat);
448   irb->Base.InternalFormat = texImage->InternalFormat;
449   irb->Base._BaseFormat = _mesa_base_tex_format(ctx, irb->Base.InternalFormat);
450   irb->Base.Width = texImage->Width;
451   irb->Base.Height = texImage->Height;
452
453   irb->Base.Delete = intel_delete_renderbuffer;
454   irb->Base.AllocStorage = intel_nop_alloc_storage;
455
456   /* Point the renderbuffer's region to the texture's region. */
457   if (irb->region != intel_image->mt->region) {
458      intel_region_release(&irb->region);
459      intel_region_reference(&irb->region, intel_image->mt->region);
460   }
461
462   /* Allocate the texture's hiz region if necessary. */
463   if (intel->vtbl.is_hiz_depth_format(intel, texImage->TexFormat)
464       && !intel_image->mt->hiz_region) {
465      intel_image->mt->hiz_region =
466         intel_region_alloc(intel->intelScreen,
467                            I915_TILING_Y,
468                            _mesa_get_format_bytes(texImage->TexFormat),
469                            texImage->Width,
470                            texImage->Height,
471                            GL_TRUE);
472      if (!intel_image->mt->hiz_region)
473         return GL_FALSE;
474   }
475
476   /* Point the renderbuffer's hiz region to the texture's hiz region. */
477   if (irb->hiz_region != intel_image->mt->hiz_region) {
478      intel_region_release(&irb->hiz_region);
479      intel_region_reference(&irb->hiz_region, intel_image->mt->hiz_region);
480   }
481
482   return GL_TRUE;
483}
484
485
486/**
487 * When glFramebufferTexture[123]D is called this function sets up the
488 * gl_renderbuffer wrapper around the texture image.
489 * This will have the region info needed for hardware rendering.
490 */
491static struct intel_renderbuffer *
492intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
493{
494   const GLuint name = ~0;   /* not significant, but distinct for debugging */
495   struct intel_renderbuffer *irb;
496
497   /* make an intel_renderbuffer to wrap the texture image */
498   irb = CALLOC_STRUCT(intel_renderbuffer);
499   if (!irb) {
500      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
501      return NULL;
502   }
503
504   _mesa_init_renderbuffer(&irb->Base, name);
505   irb->Base.ClassID = INTEL_RB_CLASS;
506
507   if (!intel_update_wrapper(ctx, irb, texImage)) {
508      free(irb);
509      return NULL;
510   }
511
512   return irb;
513}
514
515static void
516intel_set_draw_offset_for_image(struct intel_texture_image *intel_image,
517				int zoffset)
518{
519   struct intel_mipmap_tree *mt = intel_image->mt;
520   unsigned int dst_x, dst_y;
521
522   /* compute offset of the particular 2D image within the texture region */
523   intel_miptree_get_image_offset(intel_image->mt,
524				  intel_image->level,
525				  intel_image->face,
526				  zoffset,
527				  &dst_x, &dst_y);
528
529   mt->region->draw_offset = (dst_y * mt->region->pitch + dst_x) * mt->cpp;
530   mt->region->draw_x = dst_x;
531   mt->region->draw_y = dst_y;
532}
533
534/**
535 * Called by glFramebufferTexture[123]DEXT() (and other places) to
536 * prepare for rendering into texture memory.  This might be called
537 * many times to choose different texture levels, cube faces, etc
538 * before intel_finish_render_texture() is ever called.
539 */
540static void
541intel_render_texture(struct gl_context * ctx,
542                     struct gl_framebuffer *fb,
543                     struct gl_renderbuffer_attachment *att)
544{
545   struct gl_texture_image *newImage
546      = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
547   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
548   struct intel_texture_image *intel_image;
549
550   (void) fb;
551
552   ASSERT(newImage);
553
554   intel_image = intel_texture_image(newImage);
555   if (!intel_image->mt) {
556      /* Fallback on drawing to a texture that doesn't have a miptree
557       * (has a border, width/height 0, etc.)
558       */
559      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
560      _mesa_render_texture(ctx, fb, att);
561      return;
562   }
563   else if (!irb) {
564      irb = intel_wrap_texture(ctx, newImage);
565      if (irb) {
566         /* bind the wrapper to the attachment point */
567         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
568      }
569      else {
570         /* fallback to software rendering */
571         _mesa_render_texture(ctx, fb, att);
572         return;
573      }
574   }
575
576   if (!intel_update_wrapper(ctx, irb, newImage)) {
577       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
578       _mesa_render_texture(ctx, fb, att);
579       return;
580   }
581
582   DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
583       _glthread_GetID(),
584       att->Texture->Name, newImage->Width, newImage->Height,
585       irb->Base.RefCount);
586
587   intel_set_draw_offset_for_image(intel_image, att->Zoffset);
588   intel_image->used_as_render_target = GL_TRUE;
589
590#ifndef I915
591   if (!brw_context(ctx)->has_surface_tile_offset &&
592       (intel_image->mt->region->draw_offset & 4095) != 0) {
593      /* Original gen4 hardware couldn't draw to a non-tile-aligned
594       * destination in a miptree unless you actually setup your
595       * renderbuffer as a miptree and used the fragile
596       * lod/array_index/etc. controls to select the image.  So,
597       * instead, we just make a new single-level miptree and render
598       * into that.
599       */
600      struct intel_context *intel = intel_context(ctx);
601      struct intel_mipmap_tree *old_mt = intel_image->mt;
602      struct intel_mipmap_tree *new_mt;
603      int comp_byte = 0, texel_bytes;
604
605      if (_mesa_is_format_compressed(intel_image->base.TexFormat))
606	 comp_byte = intel_compressed_num_bytes(intel_image->base.TexFormat);
607
608      texel_bytes = _mesa_get_format_bytes(intel_image->base.TexFormat);
609
610      new_mt = intel_miptree_create(intel, newImage->TexObject->Target,
611				    intel_image->base._BaseFormat,
612				    intel_image->base.InternalFormat,
613				    intel_image->level,
614				    intel_image->level,
615				    intel_image->base.Width,
616				    intel_image->base.Height,
617				    intel_image->base.Depth,
618				    texel_bytes, comp_byte, GL_TRUE);
619
620      intel_miptree_image_copy(intel,
621                               new_mt,
622                               intel_image->face,
623			       intel_image->level,
624			       old_mt);
625
626      intel_miptree_release(intel, &intel_image->mt);
627      intel_image->mt = new_mt;
628      intel_set_draw_offset_for_image(intel_image, att->Zoffset);
629
630      intel_region_release(&irb->region);
631      intel_region_reference(&irb->region, intel_image->mt->region);
632   }
633#endif
634   /* update drawing region, etc */
635   intel_draw_buffer(ctx, fb);
636}
637
638
639/**
640 * Called by Mesa when rendering to a texture is done.
641 */
642static void
643intel_finish_render_texture(struct gl_context * ctx,
644                            struct gl_renderbuffer_attachment *att)
645{
646   struct intel_context *intel = intel_context(ctx);
647   struct gl_texture_object *tex_obj = att->Texture;
648   struct gl_texture_image *image =
649      tex_obj->Image[att->CubeMapFace][att->TextureLevel];
650   struct intel_texture_image *intel_image = intel_texture_image(image);
651
652   DBG("Finish render texture tid %lx tex=%u\n",
653       _glthread_GetID(), att->Texture->Name);
654
655   /* Flag that this image may now be validated into the object's miptree. */
656   if (intel_image)
657      intel_image->used_as_render_target = GL_FALSE;
658
659   /* Since we've (probably) rendered to the texture and will (likely) use
660    * it in the texture domain later on in this batchbuffer, flush the
661    * batch.  Once again, we wish for a domain tracker in libdrm to cover
662    * usage inside of a batchbuffer like GEM does in the kernel.
663    */
664   intel_batchbuffer_emit_mi_flush(intel);
665}
666
667/**
668 * Do additional "completeness" testing of a framebuffer object.
669 */
670static void
671intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
672{
673   struct intel_context *intel = intel_context(ctx);
674   const struct intel_renderbuffer *depthRb =
675      intel_get_renderbuffer(fb, BUFFER_DEPTH);
676   const struct intel_renderbuffer *stencilRb =
677      intel_get_renderbuffer(fb, BUFFER_STENCIL);
678   int i;
679
680   /*
681    * The depth and stencil renderbuffers are the same renderbuffer or wrap
682    * the same texture.
683    */
684   bool depth_stencil_are_same;
685   if (depthRb && stencilRb && depthRb == stencilRb)
686      depth_stencil_are_same = true;
687   else if (depthRb && stencilRb && depthRb != stencilRb
688	    && (fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE)
689	    && (fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE)
690	    && (fb->Attachment[BUFFER_DEPTH].Texture->Name
691		== fb->Attachment[BUFFER_STENCIL].Texture->Name))
692      depth_stencil_are_same = true;
693   else
694      depth_stencil_are_same = false;
695
696   bool fb_has_combined_depth_stencil_format =
697     (depthRb && depthRb->Base.Format == MESA_FORMAT_S8_Z24) ||
698     (stencilRb && stencilRb->Base.Format == MESA_FORMAT_S8_Z24);
699
700   bool fb_has_hiz = intel_framebuffer_has_hiz(fb);
701
702   if ((intel->must_use_separate_stencil || fb_has_hiz)
703	 && (depth_stencil_are_same || fb_has_combined_depth_stencil_format)) {
704      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
705   } else if (!intel->has_separate_stencil && depthRb && stencilRb && !depth_stencil_are_same) {
706      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
707   }
708
709   for (i = 0; i < Elements(fb->Attachment); i++) {
710      struct gl_renderbuffer *rb;
711      struct intel_renderbuffer *irb;
712
713      if (fb->Attachment[i].Type == GL_NONE)
714	 continue;
715
716      /* A supported attachment will have a Renderbuffer set either
717       * from being a Renderbuffer or being a texture that got the
718       * intel_wrap_texture() treatment.
719       */
720      rb = fb->Attachment[i].Renderbuffer;
721      if (rb == NULL) {
722	 DBG("attachment without renderbuffer\n");
723	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
724	 continue;
725      }
726
727      irb = intel_renderbuffer(rb);
728      if (irb == NULL) {
729	 DBG("software rendering renderbuffer\n");
730	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
731	 continue;
732      }
733
734      if (!intel_span_supports_format(irb->Base.Format) ||
735	  !intel->vtbl.render_target_supported(irb->Base.Format)) {
736	 DBG("Unsupported texture/renderbuffer format attached: %s\n",
737	     _mesa_get_format_name(irb->Base.Format));
738	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
739      }
740   }
741}
742
743/**
744 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
745 * We can do this when the dst renderbuffer is actually a texture and
746 * there is no scaling, mirroring or scissoring.
747 *
748 * \return new buffer mask indicating the buffers left to blit using the
749 *         normal path.
750 */
751static GLbitfield
752intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
753                                          GLint srcX0, GLint srcY0,
754                                          GLint srcX1, GLint srcY1,
755                                          GLint dstX0, GLint dstY0,
756                                          GLint dstX1, GLint dstY1,
757                                          GLbitfield mask, GLenum filter)
758{
759   if (mask & GL_COLOR_BUFFER_BIT) {
760      const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
761      const struct gl_framebuffer *readFb = ctx->ReadBuffer;
762      const struct gl_renderbuffer_attachment *drawAtt =
763         &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
764
765      /* If the source and destination are the same size with no
766         mirroring, the rectangles are within the size of the
767         texture and there is no scissor then we can use
768         glCopyTexSubimage2D to implement the blit. This will end
769         up as a fast hardware blit on some drivers */
770      if (drawAtt && drawAtt->Texture &&
771          srcX0 - srcX1 == dstX0 - dstX1 &&
772          srcY0 - srcY1 == dstY0 - dstY1 &&
773          srcX1 >= srcX0 &&
774          srcY1 >= srcY0 &&
775          srcX0 >= 0 && srcX1 <= readFb->Width &&
776          srcY0 >= 0 && srcY1 <= readFb->Height &&
777          dstX0 >= 0 && dstX1 <= drawFb->Width &&
778          dstY0 >= 0 && dstY1 <= drawFb->Height &&
779          !ctx->Scissor.Enabled) {
780         const struct gl_texture_object *texObj = drawAtt->Texture;
781         const GLuint dstLevel = drawAtt->TextureLevel;
782         const GLenum target = texObj->Target;
783
784         struct gl_texture_image *texImage =
785            _mesa_select_tex_image(ctx, texObj, target, dstLevel);
786         GLenum internalFormat = texImage->InternalFormat;
787
788         if (intel_copy_texsubimage(intel_context(ctx), target,
789                                    intel_texture_image(texImage),
790                                    internalFormat,
791                                    dstX0, dstY0,
792                                    srcX0, srcY0,
793                                    srcX1 - srcX0, /* width */
794                                    srcY1 - srcY0))
795            mask &= ~GL_COLOR_BUFFER_BIT;
796      }
797   }
798
799   return mask;
800}
801
802static void
803intel_blit_framebuffer(struct gl_context *ctx,
804                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
805                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
806                       GLbitfield mask, GLenum filter)
807{
808   /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
809   mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
810                                                    srcX0, srcY0, srcX1, srcY1,
811                                                    dstX0, dstY0, dstX1, dstY1,
812                                                    mask, filter);
813   if (mask == 0x0)
814      return;
815
816   _mesa_meta_BlitFramebuffer(ctx,
817                              srcX0, srcY0, srcX1, srcY1,
818                              dstX0, dstY0, dstX1, dstY1,
819                              mask, filter);
820}
821
822/**
823 * Do one-time context initializations related to GL_EXT_framebuffer_object.
824 * Hook in device driver functions.
825 */
826void
827intel_fbo_init(struct intel_context *intel)
828{
829   intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
830   intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
831   intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
832   intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
833   intel->ctx.Driver.RenderTexture = intel_render_texture;
834   intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
835   intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
836   intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
837   intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
838
839#if FEATURE_OES_EGL_image
840   intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
841      intel_image_target_renderbuffer_storage;
842#endif
843}
844