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