intel_fbo.c revision c18806cebf107d03751b11cc8866062c3822a56f
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/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 "main/image.h"
40
41#include "swrast/swrast.h"
42#include "drivers/common/meta.h"
43
44#include "intel_context.h"
45#include "intel_batchbuffer.h"
46#include "intel_buffers.h"
47#include "intel_blit.h"
48#include "intel_fbo.h"
49#include "intel_mipmap_tree.h"
50#include "intel_regions.h"
51#include "intel_tex.h"
52#include "intel_span.h"
53#ifndef I915
54#include "brw_context.h"
55#endif
56
57#define FILE_DEBUG_FLAG DEBUG_FBO
58
59static struct gl_renderbuffer *
60intel_new_renderbuffer(struct gl_context * ctx, GLuint name);
61
62struct intel_region*
63intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
64{
65   struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
66   if (irb && irb->mt) {
67      if (attIndex == BUFFER_STENCIL && irb->mt->stencil_mt)
68	 return irb->mt->stencil_mt->region;
69      else
70	 return irb->mt->region;
71   } else
72      return NULL;
73}
74
75/**
76 * Create a new framebuffer object.
77 */
78static struct gl_framebuffer *
79intel_new_framebuffer(struct gl_context * ctx, GLuint name)
80{
81   /* Only drawable state in intel_framebuffer at this time, just use Mesa's
82    * class
83    */
84   return _mesa_new_framebuffer(ctx, name);
85}
86
87
88/** Called by gl_renderbuffer::Delete() */
89static void
90intel_delete_renderbuffer(struct gl_renderbuffer *rb)
91{
92   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
93
94   ASSERT(irb);
95
96   intel_miptree_release(&irb->mt);
97
98   free(irb);
99}
100
101/**
102 * \see dd_function_table::MapRenderbuffer
103 */
104static void
105intel_map_renderbuffer(struct gl_context *ctx,
106		       struct gl_renderbuffer *rb,
107		       GLuint x, GLuint y, GLuint w, GLuint h,
108		       GLbitfield mode,
109		       GLubyte **out_map,
110		       GLint *out_stride)
111{
112   struct intel_context *intel = intel_context(ctx);
113   struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb;
114   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
115   void *map;
116   int stride;
117
118   if (srb->Buffer) {
119      /* this is a malloc'd renderbuffer (accum buffer), not an irb */
120      GLint bpp = _mesa_get_format_bytes(rb->Format);
121      GLint rowStride = srb->RowStride;
122      *out_map = (GLubyte *) srb->Buffer + y * rowStride + x * bpp;
123      *out_stride = rowStride;
124      return;
125   }
126
127   /* We sometimes get called with this by our intel_span.c usage. */
128   if (!irb->mt) {
129      *out_map = NULL;
130      *out_stride = 0;
131      return;
132   }
133
134   /* For a window-system renderbuffer, we need to flip the mapping we receive
135    * upside-down.  So we need to ask for a rectangle on flipped vertically, and
136    * we then return a pointer to the bottom of it with a negative stride.
137    */
138   if (rb->Name == 0) {
139      y = rb->Height - y - h;
140   }
141
142   intel_miptree_map(intel, irb->mt, irb->mt_level, irb->mt_layer,
143		     x, y, w, h, mode, &map, &stride);
144
145   if (rb->Name == 0) {
146      map += (h - 1) * stride;
147      stride = -stride;
148   }
149
150   DBG("%s: rb %d (%s) mt mapped: (%d, %d) (%dx%d) -> %p/%d\n",
151       __FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format),
152       x, y, w, h, map, stride);
153
154   *out_map = map;
155   *out_stride = stride;
156}
157
158/**
159 * \see dd_function_table::UnmapRenderbuffer
160 */
161static void
162intel_unmap_renderbuffer(struct gl_context *ctx,
163			 struct gl_renderbuffer *rb)
164{
165   struct intel_context *intel = intel_context(ctx);
166   struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb;
167   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
168
169   DBG("%s: rb %d (%s)\n", __FUNCTION__,
170       rb->Name, _mesa_get_format_name(rb->Format));
171
172   if (srb->Buffer) {
173      /* this is a malloc'd renderbuffer (accum buffer) */
174      /* nothing to do */
175      return;
176   }
177
178   intel_miptree_unmap(intel, irb->mt, irb->mt_level, irb->mt_layer);
179}
180
181
182/**
183 * Round up the requested multisample count to the next supported sample size.
184 */
185static unsigned
186quantize_num_samples(struct intel_context *intel, unsigned num_samples)
187{
188   switch (intel->gen) {
189   case 6:
190      /* Gen6 supports only 4x multisampling. */
191      if (num_samples > 0)
192         return 4;
193      else
194         return 0;
195   case 7:
196      /* Gen7 supports 4x and 8x multisampling. */
197      if (num_samples > 4)
198         return 8;
199      else if (num_samples > 0)
200         return 4;
201      else
202         return 0;
203      return 0;
204   default:
205      /* MSAA unsupported.  However, a careful reading of
206       * EXT_framebuffer_multisample reveals that we need to permit
207       * num_samples to be 1 (since num_samples is permitted to be as high as
208       * GL_MAX_SAMPLES, and GL_MAX_SAMPLES must be at least 1).  Since
209       * platforms before Gen6 don't support MSAA, this is safe, because
210       * multisampling won't happen anyhow.
211       */
212      if (num_samples > 0)
213         return 1;
214      return 0;
215   }
216}
217
218
219/**
220 * Called via glRenderbufferStorageEXT() to set the format and allocate
221 * storage for a user-created renderbuffer.
222 */
223GLboolean
224intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
225                                 GLenum internalFormat,
226                                 GLuint width, GLuint height)
227{
228   struct intel_context *intel = intel_context(ctx);
229   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
230   rb->NumSamples = quantize_num_samples(intel, rb->NumSamples);
231
232   switch (internalFormat) {
233   default:
234      /* Use the same format-choice logic as for textures.
235       * Renderbuffers aren't any different from textures for us,
236       * except they're less useful because you can't texture with
237       * them.
238       */
239      rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat,
240							 GL_NONE, GL_NONE);
241      break;
242   case GL_STENCIL_INDEX:
243   case GL_STENCIL_INDEX1_EXT:
244   case GL_STENCIL_INDEX4_EXT:
245   case GL_STENCIL_INDEX8_EXT:
246   case GL_STENCIL_INDEX16_EXT:
247      /* These aren't actual texture formats, so force them here. */
248      if (intel->has_separate_stencil) {
249	 rb->Format = MESA_FORMAT_S8;
250      } else {
251	 assert(!intel->must_use_separate_stencil);
252	 rb->Format = MESA_FORMAT_S8_Z24;
253      }
254      break;
255   }
256
257   rb->Width = width;
258   rb->Height = height;
259   rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
260
261   intel_miptree_release(&irb->mt);
262
263   DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__,
264       _mesa_lookup_enum_by_nr(internalFormat),
265       _mesa_get_format_name(rb->Format), width, height);
266
267   if (width == 0 || height == 0)
268      return true;
269
270   irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format,
271						   width, height,
272                                                   rb->NumSamples);
273   if (!irb->mt)
274      return false;
275
276   if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
277      bool ok = intel_miptree_alloc_hiz(intel, irb->mt, rb->NumSamples);
278      if (!ok) {
279	 intel_miptree_release(&irb->mt);
280	 return false;
281      }
282   }
283
284   if (irb->mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) {
285      bool ok = intel_miptree_alloc_mcs(intel, irb->mt, rb->NumSamples);
286      if (!ok) {
287         intel_miptree_release(&irb->mt);
288         return false;
289      }
290   }
291
292   return true;
293}
294
295
296#if FEATURE_OES_EGL_image
297static void
298intel_image_target_renderbuffer_storage(struct gl_context *ctx,
299					struct gl_renderbuffer *rb,
300					void *image_handle)
301{
302   struct intel_context *intel = intel_context(ctx);
303   struct intel_renderbuffer *irb;
304   __DRIscreen *screen;
305   __DRIimage *image;
306
307   screen = intel->intelScreen->driScrnPriv;
308   image = screen->dri2.image->lookupEGLImage(screen, image_handle,
309					      screen->loaderPrivate);
310   if (image == NULL)
311      return;
312
313   /* __DRIimage is opaque to the core so it has to be checked here */
314   switch (image->format) {
315   case MESA_FORMAT_RGBA8888_REV:
316      _mesa_error(&intel->ctx, GL_INVALID_OPERATION,
317            "glEGLImageTargetRenderbufferStorage(unsupported image format");
318      return;
319      break;
320   default:
321      break;
322   }
323
324   irb = intel_renderbuffer(rb);
325   intel_miptree_release(&irb->mt);
326   irb->mt = intel_miptree_create_for_region(intel,
327                                             GL_TEXTURE_2D,
328                                             image->format,
329                                             image->region);
330   if (!irb->mt)
331      return;
332
333   rb->InternalFormat = image->internal_format;
334   rb->Width = image->region->width;
335   rb->Height = image->region->height;
336   rb->Format = image->format;
337   rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
338					   image->internal_format);
339}
340#endif
341
342/**
343 * Called for each hardware renderbuffer when a _window_ is resized.
344 * Just update fields.
345 * Not used for user-created renderbuffers!
346 */
347static GLboolean
348intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
349                           GLenum internalFormat, GLuint width, GLuint height)
350{
351   ASSERT(rb->Name == 0);
352   rb->Width = width;
353   rb->Height = height;
354   rb->InternalFormat = internalFormat;
355
356   return true;
357}
358
359
360static void
361intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
362		     GLuint width, GLuint height)
363{
364   int i;
365
366   _mesa_resize_framebuffer(ctx, fb, width, height);
367
368   fb->Initialized = true; /* XXX remove someday */
369
370   if (_mesa_is_user_fbo(fb)) {
371      return;
372   }
373
374
375   /* Make sure all window system renderbuffers are up to date */
376   for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) {
377      struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
378
379      /* only resize if size is changing */
380      if (rb && (rb->Width != width || rb->Height != height)) {
381	 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
382      }
383   }
384}
385
386
387/** Dummy function for gl_renderbuffer::AllocStorage() */
388static GLboolean
389intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
390                        GLenum internalFormat, GLuint width, GLuint height)
391{
392   _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
393   return false;
394}
395
396/**
397 * Create a new intel_renderbuffer which corresponds to an on-screen window,
398 * not a user-created renderbuffer.
399 */
400struct intel_renderbuffer *
401intel_create_renderbuffer(gl_format format)
402{
403   struct intel_renderbuffer *irb;
404   struct gl_renderbuffer *rb;
405
406   GET_CURRENT_CONTEXT(ctx);
407
408   irb = CALLOC_STRUCT(intel_renderbuffer);
409   if (!irb) {
410      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
411      return NULL;
412   }
413
414   rb = &irb->Base.Base;
415
416   _mesa_init_renderbuffer(rb, 0);
417   rb->ClassID = INTEL_RB_CLASS;
418   rb->_BaseFormat = _mesa_get_format_base_format(format);
419   rb->Format = format;
420   rb->InternalFormat = rb->_BaseFormat;
421
422   /* intel-specific methods */
423   rb->Delete = intel_delete_renderbuffer;
424   rb->AllocStorage = intel_alloc_window_storage;
425
426   return irb;
427}
428
429/**
430 * Private window-system buffers (as opposed to ones shared with the display
431 * server created with intel_create_renderbuffer()) are most similar in their
432 * handling to user-created renderbuffers, but they have a resize handler that
433 * may be called at intel_update_renderbuffers() time.
434 */
435struct intel_renderbuffer *
436intel_create_private_renderbuffer(gl_format format)
437{
438   struct intel_renderbuffer *irb;
439
440   irb = intel_create_renderbuffer(format);
441   irb->Base.Base.AllocStorage = intel_alloc_renderbuffer_storage;
442
443   return irb;
444}
445
446/**
447 * Create a new renderbuffer object.
448 * Typically called via glBindRenderbufferEXT().
449 */
450static struct gl_renderbuffer *
451intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
452{
453   /*struct intel_context *intel = intel_context(ctx); */
454   struct intel_renderbuffer *irb;
455   struct gl_renderbuffer *rb;
456
457   irb = CALLOC_STRUCT(intel_renderbuffer);
458   if (!irb) {
459      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
460      return NULL;
461   }
462
463   rb = &irb->Base.Base;
464
465   _mesa_init_renderbuffer(rb, name);
466   rb->ClassID = INTEL_RB_CLASS;
467
468   /* intel-specific methods */
469   rb->Delete = intel_delete_renderbuffer;
470   rb->AllocStorage = intel_alloc_renderbuffer_storage;
471   /* span routines set in alloc_storage function */
472
473   return rb;
474}
475
476
477/**
478 * Called via glBindFramebufferEXT().
479 */
480static void
481intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
482                       struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
483{
484   if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
485      intel_draw_buffer(ctx);
486   }
487   else {
488      /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
489   }
490}
491
492
493/**
494 * Called via glFramebufferRenderbufferEXT().
495 */
496static void
497intel_framebuffer_renderbuffer(struct gl_context * ctx,
498                               struct gl_framebuffer *fb,
499                               GLenum attachment, struct gl_renderbuffer *rb)
500{
501   DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
502
503   _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
504   intel_draw_buffer(ctx);
505}
506
507/**
508 * \par Special case for separate stencil
509 *
510 *     When wrapping a depthstencil texture that uses separate stencil, this
511 *     function is recursively called twice: once to create \c
512 *     irb->wrapped_depth and again to create \c irb->wrapped_stencil.  On the
513 *     call to create \c irb->wrapped_depth, the \c format and \c
514 *     internal_format parameters do not match \c mt->format. In that case, \c
515 *     mt->format is MESA_FORMAT_S8_Z24 and \c format is \c
516 *     MESA_FORMAT_X8_Z24.
517 *
518 * @return true on success
519 */
520
521static bool
522intel_renderbuffer_update_wrapper(struct intel_context *intel,
523                                  struct intel_renderbuffer *irb,
524				  struct gl_texture_image *image,
525                                  uint32_t layer)
526{
527   struct gl_renderbuffer *rb = &irb->Base.Base;
528   struct intel_texture_image *intel_image = intel_texture_image(image);
529   struct intel_mipmap_tree *mt = intel_image->mt;
530   int level = image->Level;
531
532   rb->Format = image->TexFormat;
533   rb->InternalFormat = image->InternalFormat;
534   rb->_BaseFormat = image->_BaseFormat;
535   rb->Width = mt->level[level].width;
536   rb->Height = mt->level[level].height;
537
538   rb->Delete = intel_delete_renderbuffer;
539   rb->AllocStorage = intel_nop_alloc_storage;
540
541   intel_miptree_check_level_layer(mt, level, layer);
542   irb->mt_level = level;
543   irb->mt_layer = layer;
544
545   intel_miptree_reference(&irb->mt, mt);
546
547   intel_renderbuffer_set_draw_offset(irb);
548
549   if (mt->hiz_mt == NULL &&
550       intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
551      intel_miptree_alloc_hiz(intel, mt, 0 /* num_samples */);
552      if (!mt->hiz_mt)
553	 return false;
554   }
555
556   return true;
557}
558
559void
560intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb)
561{
562   unsigned int dst_x, dst_y;
563
564   /* compute offset of the particular 2D image within the texture region */
565   intel_miptree_get_image_offset(irb->mt,
566				  irb->mt_level,
567				  0, /* face, which we ignore */
568				  irb->mt_layer,
569				  &dst_x, &dst_y);
570
571   irb->draw_x = dst_x;
572   irb->draw_y = dst_y;
573}
574
575/**
576 * Rendering to tiled buffers requires that the base address of the
577 * buffer be aligned to a page boundary.  We generally render to
578 * textures by pointing the surface at the mipmap image level, which
579 * may not be aligned to a tile boundary.
580 *
581 * This function returns an appropriately-aligned base offset
582 * according to the tiling restrictions, plus any required x/y offset
583 * from there.
584 */
585uint32_t
586intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
587				uint32_t *tile_x,
588				uint32_t *tile_y)
589{
590   struct intel_region *region = irb->mt->region;
591   uint32_t mask_x, mask_y;
592
593   intel_region_get_tile_masks(region, &mask_x, &mask_y);
594
595   *tile_x = irb->draw_x & mask_x;
596   *tile_y = irb->draw_y & mask_y;
597   return intel_region_get_aligned_offset(region, irb->draw_x & ~mask_x,
598                                          irb->draw_y & ~mask_y);
599}
600
601/**
602 * Called by glFramebufferTexture[123]DEXT() (and other places) to
603 * prepare for rendering into texture memory.  This might be called
604 * many times to choose different texture levels, cube faces, etc
605 * before intel_finish_render_texture() is ever called.
606 */
607static void
608intel_render_texture(struct gl_context * ctx,
609                     struct gl_framebuffer *fb,
610                     struct gl_renderbuffer_attachment *att)
611{
612   struct intel_context *intel = intel_context(ctx);
613   struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
614   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
615   struct intel_texture_image *intel_image = intel_texture_image(image);
616   struct intel_mipmap_tree *mt = intel_image->mt;
617   int layer;
618
619   (void) fb;
620
621   if (att->CubeMapFace > 0) {
622      assert(att->Zoffset == 0);
623      layer = att->CubeMapFace;
624   } else {
625      layer = att->Zoffset;
626   }
627
628   if (!intel_image->mt) {
629      /* Fallback on drawing to a texture that doesn't have a miptree
630       * (has a border, width/height 0, etc.)
631       */
632      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
633      _swrast_render_texture(ctx, fb, att);
634      return;
635   }
636   else if (!irb) {
637      intel_miptree_check_level_layer(mt, att->TextureLevel, layer);
638
639      irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0);
640
641      if (irb) {
642         /* bind the wrapper to the attachment point */
643         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base);
644      }
645      else {
646         /* fallback to software rendering */
647         _swrast_render_texture(ctx, fb, att);
648         return;
649      }
650   }
651
652   if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) {
653       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
654       _swrast_render_texture(ctx, fb, att);
655       return;
656   }
657
658   irb->tex_image = image;
659
660   DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n",
661       _mesa_get_format_name(image->TexFormat),
662       att->Texture->Name, image->Width, image->Height,
663       irb->Base.Base.RefCount);
664
665   /* update drawing region, etc */
666   intel_draw_buffer(ctx);
667}
668
669
670/**
671 * Called by Mesa when rendering to a texture is done.
672 */
673static void
674intel_finish_render_texture(struct gl_context * ctx,
675                            struct gl_renderbuffer_attachment *att)
676{
677   struct intel_context *intel = intel_context(ctx);
678   struct gl_texture_object *tex_obj = att->Texture;
679   struct gl_texture_image *image =
680      tex_obj->Image[att->CubeMapFace][att->TextureLevel];
681   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
682
683   DBG("Finish render %s texture tex=%u\n",
684       _mesa_get_format_name(image->TexFormat), att->Texture->Name);
685
686   if (irb)
687      irb->tex_image = NULL;
688
689   /* Since we've (probably) rendered to the texture and will (likely) use
690    * it in the texture domain later on in this batchbuffer, flush the
691    * batch.  Once again, we wish for a domain tracker in libdrm to cover
692    * usage inside of a batchbuffer like GEM does in the kernel.
693    */
694   intel_batchbuffer_emit_mi_flush(intel);
695}
696
697/**
698 * Do additional "completeness" testing of a framebuffer object.
699 */
700static void
701intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
702{
703   struct intel_context *intel = intel_context(ctx);
704   const struct intel_renderbuffer *depthRb =
705      intel_get_renderbuffer(fb, BUFFER_DEPTH);
706   const struct intel_renderbuffer *stencilRb =
707      intel_get_renderbuffer(fb, BUFFER_STENCIL);
708   struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL;
709   int i;
710
711   DBG("%s() on fb %p (%s)\n", __FUNCTION__,
712       fb, (fb == ctx->DrawBuffer ? "drawbuffer" :
713	    (fb == ctx->ReadBuffer ? "readbuffer" : "other buffer")));
714
715   if (depthRb)
716      depth_mt = depthRb->mt;
717   if (stencilRb) {
718      stencil_mt = stencilRb->mt;
719      if (stencil_mt->stencil_mt)
720	 stencil_mt = stencil_mt->stencil_mt;
721   }
722
723   if (depth_mt && stencil_mt) {
724      if (depth_mt == stencil_mt) {
725	 /* For true packed depth/stencil (not faked on prefers-separate-stencil
726	  * hardware) we need to be sure they're the same level/layer, since
727	  * we'll be emitting a single packet describing the packed setup.
728	  */
729	 if (depthRb->mt_level != stencilRb->mt_level ||
730	     depthRb->mt_layer != stencilRb->mt_layer) {
731	    DBG("depth image level/layer %d/%d != stencil image %d/%d\n",
732		depthRb->mt_level,
733		depthRb->mt_layer,
734		stencilRb->mt_level,
735		stencilRb->mt_layer);
736	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
737	 }
738      } else {
739	 if (!intel->has_separate_stencil) {
740	    DBG("separate stencil unsupported\n");
741	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
742	 }
743	 if (stencil_mt->format != MESA_FORMAT_S8) {
744	    DBG("separate stencil is %s instead of S8\n",
745		_mesa_get_format_name(stencil_mt->format));
746	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
747	 }
748	 if (intel->gen < 7 && depth_mt->hiz_mt == NULL) {
749	    /* Before Gen7, separate depth and stencil buffers can be used
750	     * only if HiZ is enabled. From the Sandybridge PRM, Volume 2,
751	     * Part 1, Bit 3DSTATE_DEPTH_BUFFER.SeparateStencilBufferEnable:
752	     *     [DevSNB]: This field must be set to the same value (enabled
753	     *     or disabled) as Hierarchical Depth Buffer Enable.
754	     */
755	    DBG("separate stencil without HiZ\n");
756	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
757	 }
758      }
759   }
760
761   for (i = 0; i < Elements(fb->Attachment); i++) {
762      struct gl_renderbuffer *rb;
763      struct intel_renderbuffer *irb;
764
765      if (fb->Attachment[i].Type == GL_NONE)
766	 continue;
767
768      /* A supported attachment will have a Renderbuffer set either
769       * from being a Renderbuffer or being a texture that got the
770       * intel_wrap_texture() treatment.
771       */
772      rb = fb->Attachment[i].Renderbuffer;
773      if (rb == NULL) {
774	 DBG("attachment without renderbuffer\n");
775	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
776	 continue;
777      }
778
779      if (fb->Attachment[i].Type == GL_TEXTURE) {
780	 const struct gl_texture_image *img =
781	    _mesa_get_attachment_teximage_const(&fb->Attachment[i]);
782
783	 if (img->Border) {
784	    DBG("texture with border\n");
785	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
786	    continue;
787	 }
788      }
789
790      irb = intel_renderbuffer(rb);
791      if (irb == NULL) {
792	 DBG("software rendering renderbuffer\n");
793	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
794	 continue;
795      }
796
797      if (!intel->vtbl.render_target_supported(intel, rb)) {
798	 DBG("Unsupported HW texture/renderbuffer format attached: %s\n",
799	     _mesa_get_format_name(intel_rb_format(irb)));
800	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
801      }
802   }
803}
804
805/**
806 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
807 * We can do this when the dst renderbuffer is actually a texture and
808 * there is no scaling, mirroring or scissoring.
809 *
810 * \return new buffer mask indicating the buffers left to blit using the
811 *         normal path.
812 */
813static GLbitfield
814intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
815                                          GLint srcX0, GLint srcY0,
816                                          GLint srcX1, GLint srcY1,
817                                          GLint dstX0, GLint dstY0,
818                                          GLint dstX1, GLint dstY1,
819                                          GLbitfield mask, GLenum filter)
820{
821   if (mask & GL_COLOR_BUFFER_BIT) {
822      const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
823      const struct gl_framebuffer *readFb = ctx->ReadBuffer;
824      const struct gl_renderbuffer_attachment *drawAtt =
825         &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
826      struct intel_renderbuffer *srcRb =
827         intel_renderbuffer(readFb->_ColorReadBuffer);
828
829      /* If the source and destination are the same size with no
830         mirroring, the rectangles are within the size of the
831         texture and there is no scissor then we can use
832         glCopyTexSubimage2D to implement the blit. This will end
833         up as a fast hardware blit on some drivers */
834      if (srcRb && drawAtt && drawAtt->Texture &&
835          srcX0 - srcX1 == dstX0 - dstX1 &&
836          srcY0 - srcY1 == dstY0 - dstY1 &&
837          srcX1 >= srcX0 &&
838          srcY1 >= srcY0 &&
839          srcX0 >= 0 && srcX1 <= readFb->Width &&
840          srcY0 >= 0 && srcY1 <= readFb->Height &&
841          dstX0 >= 0 && dstX1 <= drawFb->Width &&
842          dstY0 >= 0 && dstY1 <= drawFb->Height &&
843          !ctx->Scissor.Enabled) {
844         const struct gl_texture_object *texObj = drawAtt->Texture;
845         const GLuint dstLevel = drawAtt->TextureLevel;
846         const GLenum target = texObj->Target;
847
848         struct gl_texture_image *texImage =
849            _mesa_select_tex_image(ctx, texObj, target, dstLevel);
850
851         if (intel_copy_texsubimage(intel_context(ctx),
852                                    intel_texture_image(texImage),
853                                    dstX0, dstY0,
854                                    srcRb,
855                                    srcX0, srcY0,
856                                    srcX1 - srcX0, /* width */
857                                    srcY1 - srcY0))
858            mask &= ~GL_COLOR_BUFFER_BIT;
859      }
860   }
861
862   return mask;
863}
864
865static void
866intel_blit_framebuffer(struct gl_context *ctx,
867                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
868                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
869                       GLbitfield mask, GLenum filter)
870{
871   /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
872   mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
873                                                    srcX0, srcY0, srcX1, srcY1,
874                                                    dstX0, dstY0, dstX1, dstY1,
875                                                    mask, filter);
876   if (mask == 0x0)
877      return;
878
879#ifndef I915
880   mask = brw_blorp_framebuffer(intel_context(ctx),
881                                srcX0, srcY0, srcX1, srcY1,
882                                dstX0, dstY0, dstX1, dstY1,
883                                mask, filter);
884   if (mask == 0x0)
885      return;
886#endif
887
888   _mesa_meta_BlitFramebuffer(ctx,
889                              srcX0, srcY0, srcX1, srcY1,
890                              dstX0, dstY0, dstX1, dstY1,
891                              mask, filter);
892}
893
894void
895intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb)
896{
897   if (irb->mt) {
898      intel_miptree_slice_set_needs_hiz_resolve(irb->mt,
899                                                irb->mt_level,
900                                                irb->mt_layer);
901   }
902}
903
904void
905intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb)
906{
907   if (irb->mt) {
908      intel_miptree_slice_set_needs_depth_resolve(irb->mt,
909                                                  irb->mt_level,
910                                                  irb->mt_layer);
911   }
912}
913
914bool
915intel_renderbuffer_resolve_hiz(struct intel_context *intel,
916			       struct intel_renderbuffer *irb)
917{
918   if (irb->mt)
919      return intel_miptree_slice_resolve_hiz(intel,
920                                             irb->mt,
921                                             irb->mt_level,
922                                             irb->mt_layer);
923
924   return false;
925}
926
927bool
928intel_renderbuffer_resolve_depth(struct intel_context *intel,
929				 struct intel_renderbuffer *irb)
930{
931   if (irb->mt)
932      return intel_miptree_slice_resolve_depth(intel,
933                                               irb->mt,
934                                               irb->mt_level,
935                                               irb->mt_layer);
936
937   return false;
938}
939
940/**
941 * Do one-time context initializations related to GL_EXT_framebuffer_object.
942 * Hook in device driver functions.
943 */
944void
945intel_fbo_init(struct intel_context *intel)
946{
947   intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
948   intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
949   intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer;
950   intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer;
951   intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
952   intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
953   intel->ctx.Driver.RenderTexture = intel_render_texture;
954   intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
955   intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
956   intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
957   intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
958
959#if FEATURE_OES_EGL_image
960   intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
961      intel_image_target_renderbuffer_storage;
962#endif
963}
964